51 E. Campbell Ave Suite 160 Campbell, CA. 95008 Copyright ©2011-2012 InterNiche Technologies Inc. email: Sales@iNiche.com support: http://www.iniche.com/support
InterNiche Technologies Inc. has made every effort to assure the accuracy of the information contained in this documentation. We appreciate any feedback you may have for improvements. Please send your comments to support@iniche.com.
The software described in this document is furnished under a license and may be used, or copied, only in accordance with the terms of such license.
Copyright © 2012 by InterNiche Technologies, Inc. All Rights Reserved
Revised: March 14, 2012
Trademarks
All terms mentioned in this document that are known to be service marks, tradenames, trademarks, or registered trademarks are property of their respective holders and have been appropriately capitalized. InterNiche Technologies Inc. cannot attest to the complete accuracy of this information. The use of a term in this document should not be regarded as affecting the validity of any service mark, tradename, trademark, or registered trademark.
This Technical reference is provided with InterNiche Technologies' embTCP library. The purpose of this document is to provide enough information so that a moderately experienced "C" programmer with a reasonable understanding of TCP/IP protocols can develop client and/or server applications using KEIL/ARM development tools.
The primary features of this library are:
Before you start using this product, it is important that you have successfully built, downloaded and executed some small program to your LPC1769 based board using KEIL/ARM development tools. It is not particularly important that this program run the FreeRTOS operating system, but only that you have some end-to-end experience with your entire development environment and that you have confidence that your hardware works.
This product is delivered pre-integrated with the FreeRTOS Operating System (v7.0.1). If you already have a FreeRTOS based product, then integration of your new communications libraries consists of following these steps:
main() function and invoke nichestack_init() after any operating system initialization.Similarly, if you are beginning with the OS as provided by InterNiche:
inmain.c and call nichestack_init() immediately following the call to TK_OS_INIT().TK_CREATE() instead of the xTaskCreate() function. All parameters are the same.TK_CREATE() must be communicated to embTCP by setting the max_user_tasks variable before stack initialization.The TCP Echo Client example application is found in the directory tcp_examples/example1. It connects to a TCP echo server, periodically sends echo requests and then validates that the data in the received response exactly matches the data sent.
Before compiling this example, you must change the "svraddrstr" parameter in example1.c to the IP address of a TCP echo server. The other parameters should not be changed for this initial test. Most Windows and Linux systems have a running TCP echo server that will respond to echo requests.
Note: The TCP Echo Client task of example1 begins running at the end of system initialization. It will immediately attempt to connect to the TCP Echo Server running at the specified address. This means the server needs to be running when the embTCP system is initialized. Otherwise, the connection request will timeout and the task will return to its task loop, where it will be deleted.
To include the example application in your project:
embsrc/inmain.c and remove the comments surrounding the call to example_init().Once your project begins to execute, it will display a message similar to the following on your "stdout":
embTCP - Licensed for XXX. 0000-0000-0000-0000 Copyright InterNiche Technologies, Inc. 1996-2012. All rights reserved. prepped 2 interfaces, initializing... LPC17xx Auto-negotiation: 100 Mbps, Full Duplex IP address of et1 : XX.XX.XX.XX Acquired IP address via DHCP client for interface: et1 IP address : 10.0.0.211 Subnet Mask: 255.255.255.0 Gateway : 10.0.0.1
The XXs in the IP address above represent the TCP address that has been assigned to the system.
This message indicates that embTCP was able to able to communicate with the DHCP server over the network in order to configure a DHCP address.
Shortly after the system has acquired a DHCP address, you should see a series of messages starting with:
tcp echo client is starting sending TCP echo request 1 to xx.xx.xx.xx TCP echo: received correct response
Additional TCP echo request and receive messages should appear about once a second until the command completes.
The file example1.c begins with some configuration parameters. With the default configuration, 10 echo requests of 255 bytes each will be sent to port 7 of the server specified by svraddrstr. TCP echo servers listen for requests on port 7. The 10 requests will be sent at the rate of 1 per second.
The TCPCLIENT structure holds the input and output buffers and the variables that are maintained across all of the echo requests.
The next section defines the TCP task info structure.
The function TK_ENTRY(tk_tc_echo) would normally be the main task loop. Most tasks run for the life of the system. However, the TCP echo task runs only long enough to send the configured number of echo requests. When it returns to the task loop, the task is deleted. Tasks must not exit or call return, but they can delete themselves.
The tec_init() routine does the following:
The tcp_send_an_echo() routine does the following:
The tcecho_loop does the following:
When the TCP echo client is ready to close for any reason, it calls tcp_client_close() to clean up the connection. The tcp_client_close() routine does the following:
The tcp_examples directory contains 3 other examples:
The directory for each example contains a readme.txt file describing the example in detail.
embTCP includes two versions of the library: Debug, which is intended for use during initial application development; and Non-Debug, which is appropriate for use in your final product. In addition to the presentation of messages and "debug printf()s", the Debug compilation provides two API functions: dtrap() and panic(). These are reduced to empty functions in the non-debug library. Note: Be sure to link the appropriate library as you build your own "Debug" and "Release" products.
Name
dtrap ()
Syntax
void dtrap (void);
Parameters
None.
Description
The dtrap() routine is called by the debug version of embTCP whenever it detects a situation that should not be occurring. The function prints the message "dtrap" and then goes into a forever loop. In general, you should eliminate or understand all causes of a call to dtrap before moving on to the release version of the code.
Returns
Nothing
Notes
dtrap() resides in embsrc/tcpdata.c and should be modified to suit the needs of the application developer.Name
panic()
Syntax
void panic(char *msg)
Parameters
| msg | printed on "stdout" |
Description
The panic() routine is called if the software detects a fatal system error. It will print and error message, call dtrap() in the debug version, and then call exit(1). You may want to add code to this routine to attempt to restart the system.
Returns
Never
Tailoring and tuning of the library is accomplished through the tcpdata.c file, provided in source code. It is in this file that you will be able to specify configuration variables for the various tasks created by the library, configure the width and depth of the packet buffer pools, and include or remove CLI commands from being linked into your final application. The paragraphs below discuss the various parts of this module in the order that they appear.
Each device on an Ethernet-based Local Area Network must have a unique 48-bit MAC address. Since these addresses are board specific, the application/porting engineer will have to determine how to read this value for his/her specific hardware and make it available through the get_mac_address() function, located in embsrc/tcpdata.c.
There are three modules specified in the in_modules array for embTCP. Only the netmain_module is required. The cli_module could be removed if your system does not use menus. The console_module could be removed if your system does not have a console.
If you have purchased additional InterNiche embedded libraries you will need to add their modules to this array, e.g., the telnet_module for embTELNET and the http_module and wbs_module for embHTTP.
max_user_tasks is the maximum number of application tasks that you will run. This value must be set in embsrc/tcpdata.c.
The in_bufq[ ] array defines the number and sizes of the buffers used to hold incoming and outgoing data packets. Each element specifies the number of packet buffers of a specific size that will be allocated at initialization time. While one could configure packet buffers of many different sizes, it normally works best to have pools of only 2 or 3 different sizes.
If there is no buffer large enough to hold a specific packet and there are enough smaller buffers, embTCP will chain buffers together in order to create a buffer of the required size. For this reason, having many smaller buffers (512 bytes or less) often makes more efficient use of buffer space than having fewer but larger buffers.
The function embTCP_config() is used to configure the variables discussed below. Please see the file tcpdata.c. The formats of the structures are defined in stkdata.h, but you should not need to refer to these. The following table describes each variable configured by embTCP_config()
| Section | Name | Default Value | Description |
|---|---|---|---|
| DHCP Client | dhcp.max_tries | 4 | Maximum number of transmissions of DHCP packet. |
| vendclass | 0 | This is an array that contains the vendor class identifier. This field can be upto DHCP_VENDCLASS_MAXLEN (32) bytes long. As its name implies, this field is vendor-specific. | |
| vendclass_len | 1 | The length (in bytes) of the vendor class identifier field. | |
| DNS Server | dns.max_tries | 4 | Maximum times (including the first) that a specific DNS name resolution request will be sent before DNS gives up and returns an error. |
| dns.retx_interval | 15 | Interval in seconds between retrying DNS requests for a specific name resolution. | |
| dns.max_entries | 6 | Number of entries in the DNS client's table. An entry can contain information from a resolved request or a name resolution request that is in progress. | |
| dns.servers[ ] |
{
"0.0.0.0",
"0.0.0.0",
"0.0.0.0"
} | DNS Server List: The IP address of DNS servers. Each address is entered as a standard IP address string in dotted notation. The maximum number of DNS server addresses (MAXDNSSERVERS) is 3 | |
| ICMP | ping.enable_resp | TRUE | Enable/Disable the sending of a ping response when a ping request is received. |
| ping.max_sessions | 2 | Each ping session contains information about one outstanding ICMP Echo packet. | |
| ping.timeout | 60 | If no response is received to a ping request within the specified number of seconds, the ping session will timeout. | |
| IPv4 | ipv4.reasm_tmo | 20 | Maximum amount of time (in seconds) to wait for reassembly of a fragmented IPv4 datagram to complete. |
| ipv4.tos | 0 | Default value of Type of Service (TOS) field in IPv4 header of outgoing packets. | |
| ipv4.ttl | 64 | Default value of Time to Live (TTL) field in IPv4 header of outgoing packets. | |
| TCP | tcp.conn_estab_tmo | 75 | The maximum time in seconds that embTCP will wait for a response to a connection request before it will return an error. |
| tcp.msl | 20 | Maximum segment lifetime. | |
| tcp.enable_noport_rst | TRUE | Enables the sending of an RST when a connection request is received for a non-existent port. (No server listening on this port). | |
| tcp.recv_space | 3000 | The maximum amount of received data that can be queued for an application. As this space fills, TCP tells the peer to send less data. | |
| tcp.send_space | 3000 | The maximum amount of data that can be queued in the send buffer. | |
| tcp.kal.idle_time | 600 | The length of time a session can be idle before embTCP will start sending keep-alive probe messages. | |
| tcp.kal.numprobes | 4 | The maximum number of probes that will be sent before the connection will be closed. | |
| tcp.kal.probe_interval | 15 | Time in seconds between keep-alive probes. | |
| UDP | udp.enable_dest_unreach | TRUE | Enables the sending of ICMP Destiniation Unreachable messages when a UDP connection request is received for a non-existent port. (No server listening on this port). |
| udp.rcvbuf_size | 4096 | UDP receive buffer size. This is the maximum amount of data that can be queued waiting to be read. It also limits the maximum size of a UDP message that can be received. |
These parameters are used to configure the tasks that are internal to embTCP, they are only read during embTCP initialization and should not be modified at runtime. Changing these values may affect the performance and stability of the embTCP product, and should only be undertaken by someone knowledgeable in the internals of the FreeRTOS operating system.
| max_user_tasks | 1 | The maximum number of user tasks that will be created using TK_CREATE. Tasks that use the embTCP API must be created using TK_CREATE. |
| netmain_priority | 5 | Task priorities of the internal embTCP tasks. The priorities of these 3 tasks can be reassigned to accommodate other user tasks, but the relative priorities of these 3 tasks should be preserved. |
| nettick_priority | 3 | |
| console_priority | 2 | |
| netmain_stksize | 1024 | Task stack sizes in bytes. These sizes are based testing with the various example programs. The stack sizes may need to be increased, depending on the functions that are executed in the context of each task. |
| nettick_stksize | 1536 | |
| console_stksize | 1024 | |
| free_rtos_tickrate_hz | Must be set to the constant, configTICK_RATE_HZ, defined in FreeRTOSconfig.h. |
The ethernet device driver uses arrays of data descriptors to describe the network data packets being transmitted and received. As receive descriptors are filled with data they are removed from the descriptor array and combined into data packets. The receive descriptors are replaced with data packets from an internal data packet pool. The size of each data packet in the pool is specified by 'eth_segment_size'. For best results, eth_segment_size should match the size of one on the buffer queues.
The number of transmit and receive descriptors are specified by eth_tx_num and eth_rx_num. The number of receive descriptors should be enough to contain several worst-case data packets. The number of transmit descriptors should be larger than the number of descriptors required to contain a worst-case data packet.
| eth_segment_size | 512 | The size (in bytes) of each receive descriptor. |
| eth_threshhold | 6*512 | The target size (in bytes) of the internal data packet pool. |
| eth_rx_num | 8 | The number of received descriptors. |
| eth_tx_num | 16 | The number of transmit descriptors. |
The user_pre_setup() routine is located in tcpdata.c. The function is called early in the initialization process before the embTCP initializes it modules and the devices. Additional code may be added to this routine to do any needed system initialization that is not part the normal embTCP port. This could include initializing devices, such as USB or video displays which are part of the developer's product.
By default user_pre_setup() copies the configuration parameters defined above in the embTCP structures and uses the ip_v4addrcfg() function to set up the IP addresses for the interface. The following is the definition of ip_v4addrcfg():
Name
in_v4addrcfg ()
Syntax
int in_v4addrcfg(char *name, char *addr, char *subnet_mask, char *gateway, uint32_t flags);
Parameters
| name | Name of the Ethernet interface (e.g., "et1"). |
| addr | IP address of the interface in dotted decimal notation. |
| subnet_mask | The network subnet mask in dotted decimal notation. |
| gateway | Address of the default router (gateway) in dotted decimal notation. |
| flags |
Bitwise-OR of:
|
Description
This function is used to provide addressing information for an interface. It is only expected to be invoked at startup time (from user_pre_setup() in tcpdata.c). If the system uses DHCP (as indicated via the 'flags' parameter), all of the address parameters can be specified as zero.
Returns
This function returns EFAILURE if the interface name is incorrect or if any of the address strings cannot be parsed successfully. Otherwise, it returns ESUCCESS.
The user_post_setup() routne is called after the system, modules, and devices have been intialized, but before the system begins its main run loop. The user could add any needed application initialization code here.
Currently the routine calls the DNS client initialization routine and initializes the ping application to enable the sending of ping requests. One or both of these calls could be removed, if the implementation will not use DNS or send ping requests.
Name
upnp_callback()
Syntax
void upnp_callback(char *name, int status);
Parameters
| name | Interface name |
| status |
The results of the IPv4 address acquisition process:
|
Description
The upnp_callback() routine is the registered callback handler for the IPv4 address acquisition manager. It will be called to indicate the result of address acquisition. The default version of this routine prints a status message in DEBUG mode, and does nothing in release mode. The following is the definition of upnbp_callback(). The user may add any desired functionality to this routine.
Returns
Nothing.
NOTE: Do not make changes to any of these header files.
The following files in this directory simply provide required defines, structure definitions, extern function prototypes.
| stkdata.h. |
Provides many defines needed by the embTCP. It defines the structures used by embTCP_config() and the component modules structures used for the configuration parameters described in the Stack Configuration Parameters section. It also defines the structures used to display embTCP statistics.
|
| embcli.h. |
|
| tcpdata.h. | Defines the parameters to the menu commands given in tcpdata.c and provides the extern prototypes for functions called by tcpdata.c |
| embtcp.h. |
|
Socket data is maintained internally in packets. A packet consists of a linked list of packet buffers. A packet is contiguous if has only one packet buffer. A packet is chained if more than one packet buffer is used to contain the packet's headers and data. When data is written to a socket, the Stack allocates a packet large enough to hold the data, copies the data into the packet buffer(s), and appends the packet to the socket's "send" queue. When data is read from a socket, the packet is removed from the socket's receive queue, the data is copied into the application's buffer and the packet is freed. The application writer does not need to be familiar with the internal organization of a packet.
Unused packet buffers are kept in free queues, sorted by packet buffer size. When a packet allocation request is made, one or more packet buffers are removed from the queue(s) and linked together to form a chained packet of sufficient length. The number of free queues and the size of packet buffers in each queue is configured by the porting engineer. The minimum packet buffer size is 128 bytes. The maximum packet buffer size will depend upon available target memory, device driver requirements, and the protocols being used.
At each stage of the embTCP initialization, each module's function is called to perform its initialization. When all modules have successfully completed a stage, initialization progresses to the next stage.
There are several boolean variables that can be tested to monitor the stages of the initialization process. These variableS are set to FALSE when initialization begins:
| iniche_init_done | Set to TRUE during post_task_setup() processing. Indicates that all NicheStack resources have been created and initialized. |
| iniche_net_ready | Set to TRUE when that network is up and that tasks can make calls into the Stack. ??Network interfaces may not be available yet. |
| iniche_os_done | Set to TRUE within the TK_OS_START() macro. Used by NicheTask to inform the scheduler that task initialization is done and task scheduling may begin. |
The ARM archicture stores bytes within a word or long word in "little-endian" host byte-order. Network data, on the other hand, is stored in "big-endian" network byte-order. The macros, htons() and ntohs(), can be used to convert 16-bit quantities between host byte-order and network byte-order. The macros, htonl() and ntohl(), can be used to convert 32-bit quantities between host byte-order and network byte-order.
#define htonl(l) ((((l >> 24) & 0x000000ff)) | \
(((l >> 8) & 0x0000ff00)) | \
(((h) & 0x0000ff00) << 8) | \
(((h) & 0x000000ff) << 24))
#define ntohl(l) htonl(l)
#define htons(s) ((((s) >> 8) & 0xff) | \
(((s) << 8) & 0xff00))
#define ntohs(s) htons(s)
This product is delivered pre-integrated with the FreeRTOS Operating System (v7.0.1). If you are beginning with the OS as provided by InterNiche, the integration of your application with embTCP consists of the following:
embTCP is initialized with a call to nichestack_init(), which has the following prototype:
int nichestack_init(unsigned int flags);
Nichestack_init returns 0 on success and -1 if there was an error. Currently the flags value is not used. Nichestack_init should be called after the board and FreeRTOS have been initialized, but before the call to start the OS.
Name
PING_CBKFN (typedef)
Syntax
typedef void (*PING_CBKFN)(ip_addr src, char *buffer, int length, uint16_t id, uint16_t seq, bool_t match, int reason, void *pio);
Parameters
| src | Source address (may be zero if timeout or module closure occured) (host byte order) |
| buffer | Received ICMP Echo Reply packet (in one contiguous buffer) or NULL |
| length | Length of received ICMP/IPv4 packet (including both IPv4 and ICMP headers) |
| id | Value of Identifier field in ICMP Echo packet (host byte order) |
| seq | Value of Sequence Number field in ICMP Echo packet (host byte order) |
| match | TRUE if contents of ICMP Echo Reply matched those of the previously transmitted ICMP Echo |
| reason | Callback code (one of PING_TIMEOUT, PING_MODULE_STOPPED, or PING_RESP_RCVD) |
| pio | Output descriptor (copied from value supplied in 'pio' to ping_send()) |
Description
The ping application client's callback function is invoked upon the receipt of an ICMP/IPv4 Echo Reply, or upon the expiration of a timeout or when the module is in the process of closing (via ping_close()). In the latter two cases, the packet parameter will be NULL.
Returns
Nothing
Name
dnc_free_hostent()
Syntax
void dnc_free_hostent(struct hostent *hep);
Parameters
| hep | Pointer to hostent data structure |
Description
This function frees a hostent structure that was previously allocated via a call to gethostbyname().
Returns
Nothing
Name
dnc_init()
Syntax
int dnc_init(void);
Parameters
None
Description
This function initializes the DNS client module.
Returns
This function can return any one of the following values:
Name
dnc_shutdown()
Syntax
void dnc_shutdown(void);
Parameters
None
Description
This function shuts down the DNS client module. It releases all resources allocated by that module. All subsequent name resolution requests will fail.
Returns
Nothing
Name
gethostbyname()
Syntax
struct hostent *gethostbyname(char *name);
Parameters
| name | Name that needs be resolved (to an IPv4 address) |
Description
This function is used to obtain the IPv4 address corresponding to a host name.
Returns
This function NULL if the resolution fails. Otherwise, it returns a pointer to a dynamically allocated hostent data structure containing (among other things) the IPv4 address that corresponds to the name.
Name
if_freenameindex()
Syntax
void if_freenameindex(struct if_nameindex *ptr);
Parameters
| ptr | Pointer to an array of struct if_nameindex structures |
Description
This function frees a previously allocated array of struct if_nameindex structures (that was created via a call to if_nameindex()).
Returns
Nothing
Name
if_indextoname()
Syntax
char *if_indextoname(unsigned int ifindex, char *ifname);
Parameters
| ifindex | Interface index (ones-based) |
| ifname | Pointer to storage for the name of interface (must be at least IF_NAMELEN bytes long) |
Description
This function converts a ones-based interface index into the corresponding interface name.
Returns
This function returns its second parameter ('ifname'). It returns NULL in the event of an error.
Name
if_nameindex()
Syntax
struct if_nameindex *if_nameindex(void);
Parameters
None
Description
This function creates and returns a dynamically allocated array of struct if_nameindex structures representing the various interfaces present in the system.
Returns
Pointer to the first element in the dynamically allocated array of struct if_nameindex structures.
Name
if_nametoindex
Syntax
unsigned int if_nametoindex(const char *ifname);
Parameters
| ifname | Name of interface |
Description
This function converts an interface name (e.g., "et1") into the corresponding ones-based interface index.
Returns
This function returns the ones-based interface index. If the interface does not exist, it returns 0.
Name
in_addrconf_acquire()
Syntax
int in_addrconf_acquire(char *name, uint32_t flags);
Parameters
| name | Name of interface |
| flags | Bitmask indicating protocols that are utilized in the address acquisition process (NETF_DHCPC (DHCP) and/or NETF_AUTOIP (auto-configuration)) |
Description
This function starts the address acquisition process for the specified interface using the protocols specified in the 'flags' parameter.
Returns
This function returns ESUCCESS if the address acquisition process was initiated successfully; otherwise, it returns EFAILURE.
Name
in_addrconf_release()
Syntax
int in_addrconf_release(char *name, uint32_t flags, bool_t restore_static);
Parameters
| name | Name of interface |
| flags | Bitmask indicating protocols that will no longer be utilized in the address acquisition process (NETF_DHCPC and/or NETF_AUTOIP) |
| restore_static | enable (TRUE) or disable (FALSE) restoration of previously configured static address (only utilized when all address configuration protocols have been disabled on the link) |
Description
This function terminates the use of the specified protocols for address acquisition on the specified interface. The interface address configuration data structures may also be cleared out.
Returns
This function returns ESUCCESS if the address release process was initiated successfully; otherwise, it returns EFAILURE.
Name
in_clrstats()
Syntax
int in_clrstats(int module_id, void *parm);
Parameters
| modid | Module identifier |
| parm | Optional parameter (currently only required to specify the interface identifier when clearing interface statistics, and can be specified as NULL for all other cases) |
Description
This function clears the statistics data structure for the specified module.
Returns
This function returns ENP_PARAM if the module identifier is not valid, or if the parameter pointer is NULL when clearing the interface module's statistics. It returns ENP_LOGIC if the caller requests clearing of queue- or socket-related statistics. Otherwise, it returns ESUCCESS.
Notes
in_getstats() for discussion of table and parameter identifiers and example.Name
in_clrtab()
Syntax
int in_clrtab(int modid, int tabid);
Parameters
| modid | Module identifier |
| tabid | Table identifier |
Description
This function is used to clear the ARP cache or the DNS client table in the TCP/IP stack.
Returns
This function returns ENP_PARAM if the module identifier or table identifier is not valid. Otherwise, it returns ESUCCESS.
Notes
in_getstats() for discussion of table and parameter identifiers and example.Name
in_getparm()
Syntax
int in_getparm(int modid, int parmid, void *valp);
Parameters
| modid | Module identifier |
| parmid | Parameter identifier |
| valp | Pointer to storage for parameter being retrieved |
Description
This function retrieves the value of the specified TCP/IP stack configuration parameter into the storage provided via 'valp'.
Returns
This function returns ENP_PARAM if any of the input parameters fails validation. Otherwise, it returns ESUCCESS.
Notes
in_getstats() for discussion of table and parameter identifiers and example.Name
in_getstats()
Syntax
int in_getstats(int modid, void *statp);
Parameters
| modid | Module identifier |
| statp | Pointer to storage for the statistics data structure that is being retrieved |
Description
This function retrieves the statistics data structure for the specified module.
Example:
int
ut_arpstats(void)
{
struct arp_stats arpstats;
int rc;
rc = in_getstats(ARP_MODULE, &arpstats);
printf("ut_arpstats: in_getstats() returned %d\n", rc);
if (rc == ESUCCESS) {
printf("arpReqsIn: %lu\n", arpstats.arpReqsIn);
printf("arpReqsOut: %lu\n", arpstats.arpReqsOut);
printf("arpRepsIn: %lu\n", arpstats.arpRepsIn);
printf("arpRepsOut: %lu\n", arpstats.arpRepsOut);
printf("arpGratReqsConflict: %lu\n", arpstats.arpGratReqsConflict);
printf("arpGratRepsConflict: %lu\n", arpstats.arpGratRepsConflict);
}
return (rc);
}
Notes
Returns
This function returns ENP_PARAM if the module identifier is not valid, or if the pointer to the statistics data structure is NULL, or if the socket type field is invalid when the caller requests socket-related statistics. Otherwise, it always returns ESUCCESS.
Name
in_setparm()
Syntax
int in_setparm(int modid, int parmid, void *valp);
Parameters
| modid | Module identifier |
| parmid | Parameter identifier |
| valp | Pointer to storage for parameter being configured |
Description
This function sets the value of the specified TCP/IP stack configuration parameter from data provided via 'valp'.
Returns
This function returns ENP_PARAM if any of the input parameters fails validation. Otherwise, it returns ESUCCESS.
Notes
in_getstats() for discussion of table and parameter identifiers and example.Name
inet_ntop()
Syntax
const char *inet_ntop(int af, const void *addr, char *str, size_t size);
Parameters
| af | Address family (AF_INET) |
| addr | Pointer to storage for IPv4 address ('ip_addr') in network byte order |
| str | Pointer to storage for string that will contain IPv4 address in dotted decimal notation |
| size | Length of output buffer ('str') |
Description
This functions converts a binary representation of an IPv4 address (in network byte order) into a string in dotted decimal notation. The output buffer must be at least 16 bytes long.
Returns
This function returns NULL if it encountered an error; otherwise, it returns the third argument ('str').
Name
inet_pton()
Syntax
int inet_pton(int af, const char *src, void *dst);
Parameters
| af | Address family (AF_INET) |
| src | Pointer to string containing IPv4 address in dotted decimal notation |
| dst | Pointer to storage for IPv4 address ('ip_addr') where the results of the conversion will be stored (in network byte order) |
Description
This functions converts a string containing an IPv4 address in dotted decimal notation into its equivalent binary representation (in network byte order).
Returns
This function returns 0 if the conversion was successful. A non-zero return value indicates a failure.
Name
ping_close()
Syntax
void ping_close(void);
Parameters
None
Description
This function shuts down the ping application module. It releases all resources allocated by that module. All subsequent outbound ping requests will fail.
Returns
Nothing
Name
ping_init()
Syntax
int ping_init(void);
Parameters
None
Description
This function initializes the ping module. It allocates a buffer that will contain the ping session table, and also sets the size of the session table.
Returns
This function can return any one of the following values:
Name
ping_send()
Syntax
int ping_send(ip_addr dest, char *data, int length, uint16_t id, uint16_t seq, PING_CBKFN cbkp, void *pio);
Parameters
| dest | IPv4 destination address (host byte order) |
| data | Pointer to data (for insertion into Data portion of ICMP Echo packet) (may be NULL) |
| length | Length of data (pointed to by 'data') |
| id | Value of Identifier field in ICMP Echo packet (host byte order) |
| seq | Value of Sequence Number field in ICMP Echo packet (host byte order) |
| cbkp | Callback function (to be invoked) when an ICMP Echo Reply is received |
| pio | Output descriptor (returned to application in PING_CBKFN callback function) |
Description
This function creates and transmits an ICMP/IPv4 Echo packet.
Returns
This function returns ESUCCESS or a negative error code.
extern long t_socket (int, int, int); extern int t_bind (long, struct sockaddr *, int); extern int t_listen (long, int); extern long t_accept (long, struct sockaddr *, int *); extern int t_connect (long, struct sockaddr *, int); extern int t_getpeername (long, struct sockaddr *, int *); extern int t_getsockname (long, struct sockaddr *, int *); extern int t_setsockopt (long, int, int, void *, int); extern int t_getsockopt (long, int, int, void *, int); extern int t_recv (long, char *, int, int); extern int t_recvfrom (long s, char * buf, int len, int flags, struct sockaddr *, int *); extern int t_send (long, char *, int, int); extern int t_sendto (long s, char * buf, int len, int flags, struct sockaddr *, int); extern int t_shutdown (long, int); extern int t_socketclose (long); extern int t_errno (long s); extern int t_select(fd_set * in, fd_set * out, fd_set * ev, long tmo_seconds);
This section is documentation for the embTCP Sockets layer. Sockets is an API, primarily used today for TCP programming, which was developed during the early 1980s at U.C. Berkeley for UNIX. Dozens of books and tutorials are available for Sockets programming (one of the compelling arguments for their use), so this section is devoted to functional descriptions of the Sockets subset as supported by embTCP. It is not a tutorial.
The calls documented in this section are compatible with those on UNIX systems insofar as TCP use goes. Example networking code from other Sockets-based systems should work here, and most of what is in the books and tutorials apply as well. We've tried to update the man-pages herein to reflect any differences there are.
One general difference is that all the function names in the embTCP package start with "t_", e.g. socket() is t_socket(). This is so that embedded systems which already use some of the socket names will not have a conflict at link time.
Another is the UNIX errno mechanism has been replaced by an error holder attached to each socket structure and assigned a value whenever an error occurs. Thus when a socket call indicates failure, such as t_recv() returning -1, you can examine this member or call t_errno(long s) to find out what went wrong. Possible values for Sockets errors are listed below. These are a subset of the standard Berkeley errors.
/* BSD Sockets errors */ #define ENOBUFS 1 #define ETIMEDOUT 2 #define EISCONN 3 #define EOPNOTSUPP 4 #define ECONNABORTED 5 #define EWOULDBLOCK 6 #define ECONNREFUSED 7 #define ECONNRESET 8 #define ENOTCONN 9 #define EALREADY 10 #define EINVAL 11 #define EMSGSIZE 12 #define EPIPE 13 #define EDESTADDRREQ 14 #define ESHUTDOWN 15 #define ENOPROTOOPT 16 #define EHAVEOOB 17 #define ENOMEM 18 #define EADDRNOTAVAIL 19 #define EADDRINUSE 20 #define EAFNOSUPPORT 21 #define EINPROGRESS 22 #define ELOWER 23 #define ENOTSOCK 24 #define EIEIO 27 #define ETOOMANYREFS 28 #define EFAULT 29 #define ENETUNREACH 30
Name
t_socket()
Syntax
long t_socket (int domain, int type, int protocol);
Parameters
| domain | Communication domain (AF_INET) |
| type | Socket type (SOCK_STREAM or SOCK_DGRAM) |
| protocol | 0 |
Description
t_socket() creates an endpoint for communication and returns a descriptor. The domain parameter specifies a communications domain within which communication will take place; this selects the protocol family which should be used. The protocol family generally is the same as the address family for the addresses supplied in later operations on the socket. These families are defined in the include file embtcp.h. The only currently understood format is:
AF_INET or PF_INET (ARPA Internet protocols)
The socket has the indicated type, which specifies the semantics of communication. Currently defined types are:
SOCK_STREAM /* TCP*/ SOCK_DGRAM /* UDP */
A SOCK_STREAM type provides sequenced, reliable, two-way connection based byte streams. A SOCK_DGRAM socket provides connectinless, unreliable data transfer to an application.
Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a t_connect() call. Once connected, data may be transferred using t_send() and t_recv() calls. When a session has been completed, a t_socketclose() may be performed. Out-of-band data may also be transmitted as described in the t_send() page and received as described in t_recv().
The communications protocols used to implement a SOCK_STREAM ensure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, then the connection is considered broken and calls will indicate an error with -1 returns and with ETIMEDOUT as the return code from t_errno(). An error is then indicated if no response can be elicited on an otherwise idle connection for a extended period (such as five minutes).
SOCK_DGRAM sockets allow sending of datagrams to correspondents named in t_sendto() calls. Datagrams are generally received with t_recvfrom(), which returns the next datagram with its return address.
The operation of sockets is controlled by socket level options. These options are defined in the file embtcp.h. t_getsockopt() and t_setsockopt() are used to get and set options, respectively.
Returns
A return value of -1 from t_socket() indicates failure. Any other return value indicates success.
See Also
t_accept, t_bind, t_connect, t_getsockname, t_getsockopt, t_listen, t_recv, t_select, t_send, t_shutdown
Name
t_listen()
Syntax
int t_listen(long s, int backlog);
Parameters
| s | Socket identifier |
| backlog | Used to compute a limit on the maximum number of connections that can be pending in the completed (those for which the TCP three-way handshake has completed) and partially completed (those for which the TCP three-way handshake has started, but isn't complete) queues. |
Description
To accept connections, a socket is first created with t_socket(), a backlog for incoming connections is specified with t_listen() and then the connections are accepted with t_accept(). The t_listen() call applies only to sockets of type SOCK_STREAM. The backlog parameter defines the maximum length for the queue of pending connections (not maximum open connections).
The computation is:
val = MIN(backlog, 5); limit = 3 * val / 2;
If a connection request arrives with the queue full the client will receive an error with an indication of ECONNREFUSED.
All incoming connection requests (such as those from a HTTP client (Web browser)) start off in the incomplete connection queue (when a TCP segment containing the SYN is received), and move to the completed connection queue after the successful completion of the three-way handshake. When the server application executes t_accept(), it will pick up the first available connection from the completed connection queue.
Returns
Returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_connect()
Syntax
int t_connect(long s, struct sockaddr *name, int namelen);
Parameters
| s | Socket identifier |
| name | Pointer to struct sockaddr_in structure containing addressing information for remote end (peer) |
| namelen | Length of sockaddr_in structure (bytes) |
Description
The parameter s is a socket. If it is of type SOCK_DGRAM, then this call specifies the peer with which the socket is to be associated; the address to which datagrams are sent and the only address from which datagrams are received. If it is of type SOCK_STREAM, then this call attempts to make a connection to another socket. The other socket is specified by name which is an address in the communications space of the socket. Each communications space interprets the name parameter in its own way.
Datagrams may use t_connect() multiple times to change their association. Datagram may also dissolve the association by connecting to an invalid address, such as a zero address.
Returns
This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_socketclose()
Syntax
int t_socketclose(long s);
Note: this is just close() on traditional Sockets systems.
Parameters
| s | Socket identifier |
Description
The t_socketclose() call causes all of a full-duplex connection on the socket associated with s to be shut down. Once a socket is closed, no further socket calls should be made with it.
Returns
This returns 0 on success. On failure, it returns -1.
See Also
Name
t_errno ()
Syntax
int t_errno(long s);
Parameters
| s | Socket identifier |
Description
This function returns the error associated with the specified socket.
Returns
This function returns ENOTSOCK if the socket identifier is not valid. Otherwise, it returns the error associated with the specified socket.
Name
t_select()
Syntax
int t_select (fd_set * readfds, fd_set * writefds, fd_set * exceptfds, long tv);
void FD_SET (long so, fd_set * set)
void FD_CLR (long so, fd_set * set)
void FD_ISSET (long so, fd_set * set)
void FD_ZERO (fd_set * set)
Parameters
| s | Socket identifier |
| readfds | Set of descriptors that an application will wait to become ready for reading |
| writefds | Set of descriptors that an application will wait to become ready for writing |
| exceptfds | Set of descriptors that an application will wait for occurence of an exceptional condition on |
| tv | Timeout duration (seconds) |
Description
t_select() examines the socket descriptor sets whose addresses are passed in readfds, writefds, and exceptfds to see if some of their descriptors are ready for reading, ready for writing or have an exception condition pending. On return, t_select() replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation. The total number of ready descriptors in all the sets is returned. Any of readfds, writefds, and exceptfds may be given as NULL pointers if no descriptors are of interest. Selecting true for reading on a socket descriptor upon which a t_listen() call has been performed indicates that a subsequent t_accept() call on that descriptor will not block.
In the standard Berkeley UNIX Sockets API, the descriptor sets are stored as bit fields in arrays of integers. This works in the UNIX environment because under UNIX socket descriptors are file system descriptors which are guaranteed to be small integers that can be used as indexes into the bit fields. In the embTCP stack, socket descriptor are pointers and thus a bit field representation of the descriptor sets is not feasible. Because of this, the embTCP Sockets API differs from the Berkeley standard in that the descriptor sets are represented as instances of the following structure:
typedef struct fd_set { /* the select socket array manager */
unsigned fd_count; /* how many are SET? */
long fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
Instead of a socket descriptor being represented in a descriptor set via an indexed bit, an embTCP socket descriptor is represented in a descriptor set by its presence in the fd_array field of the associated fd_set structure. Despite this non-standard representation of the descriptor sets themselves, the following standard entry points are provided for manipulating such descriptor sets: FD_ZERO(&fdset) initializes a descriptor set fdset to the null set. FD_SET(fd, &fdset) includes a particular descriptor, fd, in fdset. FD_CLR(fd, &fdset) removes fd from fdset. FD_ISSET(fd, &fdset) is nonzero if fd is a member of fdset, zero otherwise. These entry points behave according to the standard Berkeley semantics.
The porting engineer should be aware that the value of FD_SETSIZE defines the maximum number of descriptors that can be represented in a single descriptor set. The default value of FD_SETSIZE of 12 is defined in emb_h/embtcp.h.
Another difference between the Berkeley and embTCP t_select() calls is the representation of the timeout parameter. Under Berkeley Sockets, the timeout parameter is represented by a pointer to a structure. Under embTCP Sockets, a timeout value is specified by the tv parameter, which defines the maximum number of millliseconds that should elapse before the call to t_select() returns. A tv parameter value of 0 implies that t_select() should return immediately (effectively a poll of the sockets in the descriptor set). The value INFINITE_DELAY is used to specify that t_select() block forever unless one of its descriptors becomes ready. The longest possible non-infinite delay is 0x7FFFFFFF milliseconds, which is about 24.86 days.
The final difference between the Berkeley and embTCP versions of t_select() is the absence in the embTCP version of the Berkeley width parameter. The width parameter is of use only when descriptor sets are represented as bit arrays and was thus deleted in the embTCP implementation.
Returns
t_select() returns a non-negative value on success. A positive value indicates the number of ready descriptors in the descriptor sets. 0 indicates that the time limit specified by tv expired.
See Also
t_accept, t_connect, t_listen, t_recv, t_send
Notes
Under rare circumstances, t_select() may indicate that a descriptor is ready for writing when in fact an attempt to write would block. This can happen if system resources necessary for a write are exhausted or otherwise unavailable. If an application deems it critical that writes to a file descriptor not block, it should set the descriptor for non-blocking I/O. See discussion of t_setsockopt.
Name
t_recv()
t_recvfrom()
Syntax
int t_recv(long s, char * buf, int len, int flags);
int t_recvfrom(long s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);
Parameters
| s | Socket identifier |
| buf | Start address of buffer where received data will be copied into |
| len | Length of data to be sent |
| flags | Flags for receiving process (e.g., MSG_PEEK) |
| from | Pointer to struct sockaddr_in structure containing addressing information for the remote end |
| fromlen | Pointer to storage for length of sockaddr_in structure (bytes) |
Description
s is a socket created with t_socket(). t_recv() and t_recvfrom() are used to receive messages from another socket. t_recv() may be used only on a connected socket (see t_connect), while t_recvfrom() may be used to receive data on a socket whether it is in a connected state or not.
If from is not a NULL pointer, the source address of the message is filled in. fromlen is a value-result parameter, initialized to the size of the buffer associated with from, and modified on return to indicate the actual size of the address stored there. The length of the message is returned. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from (see t_socket).
If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is non-blocking (see t_setsockopt) in which case -1 is returned with the external variable t_errno set to EWOULDBLOCK.
Note that t_recv() will return an EPIPE if an attempt is made to read from an unconnected socket.
The t_select() call may be used to determine when more data arrive.
The flags parameter is formed by OR-ing one or more of the following:
| MSG_OOB | Read any "out-of-band" data present on the socket, rather than the regular "in-band" data. |
| MSG_PEEK | "Peek" at the data present on the socket; the data are returned, but not consumed, so that a subsequent receive operation will see the same data. |
Returns
These calls return the number of bytes received, or -1 if an error occurred. On failure, they set an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_send()
t_sendto()
Syntax
int t_send(long s, char *buf, int len, int flags);
int t_sendto(long s, char *buf, int len, int flags, struct sockaddr *to, int tolen);
Parameters
| s | Socket identifier |
| buf | Start address of data to be sent |
| len | Length of data to be sent |
| flags | Flags for sending process (e.g., MSG_OOB) |
| to | Pointer to struct sockaddr_in structure containing addressing information for the remote end |
| tolen | Length of sockaddr_in structure (bytes) |
Description
t_send() and t_sendto() are used to transmit the message addressed by buf to another socket. t_send() may be used only when the socket is in a connected state, while t_sendto() may be used at any time, in which case the address of the target is given by the to parameter. The length of the message is given by len.
No indication of failure to deliver is implicit in a t_send(). Locally detected errors are indicated by a return value of -1.
If no messages space is available at the socket to hold the message to be transmitted, then t_send() normally blocks, unless the socket has been placed in non-blocking I/O mode. The t_select() call may be used to determine when it is possible to send more data.
The flags parameter may include one or more of the following:
#define MSG_OOB 0x1 /* process out-of-band data */
The flag MSG_OOB is used to send "out-of-band" data on sockets that support this notion (e.g. SOCK_STREAM); the underlying protocol must also support "out-of-band" data.
Returns
The call returns the number of characters sent, or -1 if an error occurred. On failure, it sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_accept()
Syntax
long t_accept(long s, struct sockaddr *addr, int *addrlen);
Parameters
| s | Socket identifier |
| addr | Pointer to struct sockaddr_in structure containing addressing information for the remote end in newly accepted connection |
| addrlen | Pointer to storage for length of sockaddr_in structure (bytes) |
Description
The argument s is a socket that has been created with t_socket(), bound to an address with t_bind() and is listening for connections after a t_listen(). t_accept() extracts the first connection on the queue of pending connections, creates a new socket with the same properties as s and allocates a new file descriptor for the socket. If no pending connections are present on the queue, and the socket is not marked as non-blocking, t_accept() blocks the caller until a connection is present. If the socket is marked non-blocking and no pending connections are present on the queue, t_accept() returns an error as described below. The accepted socket is used to read and write data to and from the socket which connected to this one; it is not used to accept more connections. The original socket s remains open for accepting further connections.
The argument addr is a result parameter that is filled in with the address of the connecting entity as known to the communications layer, i.e. the exact format of the addr parameter is determined by the domain in which the communication is occurring. The addrlen is a value-result parameter. It should initially contain the amount of space pointed to by addr. On return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types, currently with SOCK_STREAM.
It is possible to t_select() a socket for the purposes of doing an t_accept() by selecting it for read.
Returns
t_accept() returns a non-negative descriptor for the accepted socket on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_bind()
Syntax
int t_bind(long s, struct sockaddr *name, int namelen);
Parameters
| s | Socket identifier |
| name | Pointer to struct sockaddr_in structure containing addressing information for local end |
| namelen | Length of sockaddr_in structure (bytes) |
Description
t_bind() sets the local endpoint address and port number for a socket. When a socket is created with t_socket() it exists in a name space (address family) but has no name assigned. t_bind() requests that the name pointed to by name be assigned to the socket.
Returns
t_bind() returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_shutdown()
Syntax
int t_shutdown(long s, int how);
Parameters
| s | Socket identifier |
| how | Type of shutdown (SHUT_RD, SHUT_WR, or SHUT_RDWR) |
Description
The t_shutdown() call causes all or part of a full-duplex connection on the socket associated with s to be shut down. If how is SHUT_RD, then further receives will be disallowed. If how is SHUT_WR, then further sends will be disallowed. If how is SHUT_RDWR, then further sends and receives will be disallowed.
Returns
This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_getpeername()
Syntax
int t_getpeername(long s, struct sockaddr *name, int * addrlen);
Parameters
| s | Socket identifier |
| name | Pointer to struct sockaddr_in structure containing addressing information for local end |
| addrlen | Pointer to storage for length of sockaddr_in structure (bytes) |
Description
Fills in the passed struct sockaddr with the IP addressing information of the connected host.
The addrlen is a value-result parameter and should initially contain the amount of space pointed to by name.
Returns
This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_getsockname()
Syntax
int t_getsockname(long s, struct sockaddr *name, int * addrlen);
Parameters
| s | Socket identifier |
| name | Pointer to struct sockaddr_in structure containing addressing information for local end |
| addrlen | Pointer to storage for length of sockaddr_in structure (bytes) |
Description
t_getsockname() returns the current name for the specified socket, in the passed struct sockaddr.
The addrlen is a value-result parameter and should initially contain the amount of space pointed to by name.
Returns
This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
t_getsockopt()
t_setsockopt()
Syntax
int t_getsockopt(long s, int level, int optname, char *optval, int optlen);
int t_setsockopt(long s, int level, int optname, char *optval, int optlen);
Parameters
| s | Socket identifier |
| level | Level of socket option (IP_OPTIONS or SOL_SOCKET) |
| optname | Name of socket option (e.g., SO_ERROR) |
| optval | Pointer to storage for socket option (for reading (get) or writing (set)) |
| optlen | Size of storage pointed to by 'optval' |
Description
t_getsockopt() and t_setsockopt() manipulate options associated with a socket. The optname parameter identifies an option that is to be set with t_setsockopt() or retrieved with t_getsockopt().
The parameter optval is used to specify option values for t_setsockopt(). On calls to t_setsockopt() it generally contains a pointer to a variable or structure, the contents of which will define the value of the option to be set. On calls to t_getsockopt() it generally points to a variable or structure into which the value for the requested option is to be returned.
The following options are recognized by embTCP:
| Option Name | Description |
|---|---|
| IP_TTL_OPT | set TTL field in IPv4 header for outgoing IPv4 datagrams |
| IP_TOS | set TOS field in IPv4 header for outgoing IPv4 datagrams |
| SO_BIO | configure socket to use blocking I/O |
| SO_ERROR | retrieve and clear last error on the socket |
| SO_KEEPALIVE | enable or disable TCP keepalives |
| SO_LINGER | enable or disable linger on close if data present |
| SO_NBIO | configure socket to use non-blocking I/O |
| SO_NONBLOCK | configure socket to use blocking or non-blocking I/O |
| SO_OOBINLINE | enable or disable inline reception of TCP out-of-band data |
| SO_RCVBUF | maximum amount of data that can be queued in socket's receive buffer |
| SO_REUSEADDR | enable or disable local address reuse |
| SO_RXDATA | number of bytes queued in socket's receive buffer |
| SO_SNDBUF | maximum amount of data that can be queued in socket's send buffer |
| SO_TXDATA | number of bytes queued in socket's send buffer |
| SO_TYPE | retrieve the type of the socket (SOCK_STREAM or SOCK_DGRAM) |
| TCP_NODELAY | enable or disable Nagle algorithm |
embTCP supports get/set operations for socket options as follows:
| Option Name | level | type | supported operation |
|---|---|---|---|
| IP_TTL_OPT | IP_OPTIONS | int | get, set |
| IP_TOS | IP_OPTIONS | int | get, set |
| SO_BIO | SOL_SOCKET | <none> | set |
| SO_ERROR | SOL_SOCKET | int | get |
| SO_KEEPALIVE | SOL_SOCKET | int | get, set |
| SO_LINGER | SOL_SOCKET | struct linger | get, set |
| SO_NBIO | SOL_SOCKET | <none> | set |
| SO_NONBLOCK | SOL_SOCKET | int | get, set |
| SO_OOBINLINE | SOL_SOCKET | int | get, set |
| SO_RCVBUF | SOL_SOCKET | int | get, set |
| SO_REUSEADDR | SOL_SOCKET | int | get, set |
| SO_RXDATA | SOL_SOCKET | int | get |
| SO_SNDBUF | SOL_SOCKET | int | get, set |
| SO_TXDATA | SOL_SOCKET | int | get |
| SO_TYPE | SOL_SOCKET | int | get |
| TCP_NODELAY | SOL_SOCKET | int | get, set |
The include file embtcp.h contains definitions for option names, described below. Most options take a pointer to an int variable for optval. For t_setsockopt(), the variable addressed by the parameter should be non-zero to enable a Boolean option or zero if the option is to be disabled.
SO_LINGER uses a struct linger parameter defined in embtcp.h. This parameter specifies the desired state of the option and the linger interval (see below).
SO_REUSEADDR indicates that the rules used in validating addresses supplied in a t_bind() call should allow reuse of local addresses.
SO_KEEPALIVE enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken. If the process is waiting in t_select() when the connection is broken, t_select() returns true for any read or write events selected for the socket.
SO_LINGER controls the action taken when unsent messages are queued on socket and a t_socketclose() is performed. If the socket promises reliable delivery of data and SO_LINGER is set, the system will block the caller on the t_socketclose() attempt until it is able to transmit the data or until it decides it is unable to deliver the information (a timeout period, termed the linger interval, is specified in the t_setsockopt() call when SO_LINGER is requested). If SO_LINGER is disabled and a t_socketclose() is issued, the system will process the close in a manner that allows the caller to continue as quickly as possible.
With protocols that support out-of-band data, the SO_OOBINLINE option requests that out-of-band data be placed in the normal data input queue as received. It will then be accessible with t_recv() calls without the MSG_OOB flag.
SO_SNDBUF and SO_RCVBUF are options to adjust the normal buffer sizes allocated for the output and input buffers respectively. The buffer size may be increased for high-volume connections or may be decreased to limit the possible backlog of incoming data. The system places an absolute limit on these values.
SO_TYPE and SO_ERROR are options used only with t_getsockopt(). SO_TYPE returns the type of the socket, for example SOCK_STREAM. SO_ERROR returns any pending error on the socket and clears the error status. It may be used to check for asynchronous errors on connected datagram sockets or for other asynchronous errors.
The TCP_NODELAY disables the Nagle algorithm, and prevents attempts to coalesce small packets less than the TCP_MSS, while awaiting acknowledgement for data already sent.
The options SO_NONBLOCK, SO_NBIO, and SO_BIO are unique to the InterNiche stack (these options do not appear in the Berkeley Sockets API) and are used to control whether a socket uses blocking or non-blocking IO.
SO_NBIO is used to specify that a socket use non-blocking IO. SO_BIO is used to specify that a socket use blocking IO. The use of t_setsockopt() to set these options is different than that of the standard Boolean options in that the value in optval is not used. All that is necessary is to specify the appropriate option name in optname.
Returns
The value returned for the SO_KEEPALIVE, SO_OOBINLINE, and SO_REUSEADDR socket options in a t_getsockopt() call is the corresponding bitmask (e.g., SO_KEEPALIVE (8), as defined in embtcp.h) if the option is enabled, and zero otherwise.
For all others, 0 is returned upon success. On failure, they return -1 and set an internal t_errno to one of the errors listed in Sockets Errors to indicate the error. The t_errno can be retrieved by a call to t_errno(s).
See Also
Name
get_mac_address()
Syntax
int get_mac_address(int iface, uint8_t *emac);
Parameters
| iface | Address of the array to contain the Ethernet address. |
| emac | Specifies the ethernet interface; the first interface is 0. |
Description
The ethernet driver calls get_mac_address() to obtain the 48-bit MAC address of the hardware interface. The function obtains the 6-byte value from a user-defined location, such as non-volatile memory, and copies it into the array pointed to by the emac parameter.
Returns
The function returns 0 if the copy was successful, and -1 if there was a parameter error or the MAC address was unavailable.
Notes
For a chip with a single ethernet device, 0 is the only valid iface parameter value.
Name
emac_phy_init()
Syntax
int emac_phy_init(void);
Parameters
None.
Description
The ethernet driver calls emac_phy_init() to initialize the external PHY chip. In order to accomodate different PHY chips, the implementation of the initialization function is the responsibility of the porting engineer. A sample implementation for the DP83848C PHY chip is provided in phy_dp83848.c.
The initialization function should:
If the link is successfully established, either through auto-negotiation or by programming the link speed and duplex mode, the emac_phy_init() function must call eth_setlink() to communicate the negotiated link characteristics to the ethernet device driver. Refer to the sample emac_phy_init() implementation for an example of the eth_setlink() call.
Returns
emac_phy_init() returns 0 if the PHY initialization was successful and a negative error code if the initialization failed. If the PHY initialization fails, the ethernet device initialization fails, and the ethernet interface is considered unavailable.
Notes
The PHY chip must be connected to the network in order to initialize the PHY using the auto-negotiation protocol.
The usleep function can be used to insert short delays into the initialization process. The delay is accomplished via a software loop. The loop parameters may need to be adjusted for the actual system clock speed.
tcpdata.c carries a table of CLI commands and the implementation of a demonstration command: user1_cli(). The CLI commands are described as man pages in the CLI Commands section. The implementation of user1_cli() was designed to illustrate the major aspects of the CLI Interface and its helper functions.
embTCP's Command Line Interface (CLI) provides access to InterNiche's embedded products commands and statistics function. Additional commands and menus can be added and these will be treated exactly like the pre-defined commands. Broadly speaking, the CLI mechanism parses "command line input", and uses the initial tokens to identify the desired "C" function. Any parameters that follow the initial tokens are parsed and passed to the menu routine in a standardized format.
CLI commands are parsed and processed by the CLI module. The command definitions are grouped within menus which are part of a NicheStack module. All command for the embTCP library are grouped within a single menu. However if you have purchased other InterNiche embedded libraries, they will each have separate menus.
Throughout the discussion below, the example command, "user1_cli()", located in tcpdata.c will be used to illustrate the various CLI structures and mechanisms.
cli_menu structure in embcli.h
/* CLI menu description */
struct cli_menu {
char *name; /* The name of the menu */
int ncmds; /* Number of commands in the menu */
struct cli_cmd *cmds; /* Array of structures describing each command */
};
The following is the definition of the menu for the embTCP module (from tcpdata.c):
struct cli_menu netmain_nt = {
"embtcp",
sizeof(net_cmds)/sizeof(struct cli_cmd),
&net_cmds[0],
};
Each command within a menu is defined by the cli_cmd structure:
/* CLI command element */
struct cli_cmd {
char *name; /* command name */
char *desc; /* command description displayed to user*/
int (*func)(void *); /* pointer to the CLI command function that
* handles the command
int nparms; /* number of parameters */
struct cli_parm *parms; /* pointer to the parameter array */
};
The following is the definition of the "user1" example menu command:
#if INICHE_CLICMD_USER1 == 1
{
"user1", /* Command name */
"user-defined CLI command", /* Command description seen by the user */
&user1_cli, /* Function that will handle the command */
sizeof(user1_parms)/sizeof(struct cli_parm), /* Number of parameters */
&user1_parms[0], /* Pointer to parameter array for this command */
},
#endif
Note that the command is surrounded by #if INICHE_CLICMD_USER1 == 1. The definitions of the cli_cmd structures for each command in embTCP are surrounded by similar defines. This allows you to control exactly which commands will be included in the build.
Each command within a menu may take from zero to many parameters (options). Parameters are defined by the cli_parm structure:
/* CLI parameter definition */
struct cli_parm {
char option; /* letter that identifies (selects) the option */
char opttype; /* CLI data type */
};
Each parameter consists of a letter preceded by a hyphen and optionally followed by a value. The parameter letter and the parameter value are separated by "whitespace". The parameter letter is not case-sensitive. In order to simplify command processing for small embedded systems, multiple letter identifiers are not allowed and. options cannot be combined; that is, there must be whitespace between each option.
The type of each parameter is checked as the command is parsed. Supported parameter types are:
| CLI_NONE | No parameter value. The command function can test for the presence or absence of the parameter. |
| CLI_INT | Signed 32-bit integer. |
| CLI_UINT | Unsigned 32-bit integer. |
| CLI_STRING | A character string delimited by "whitespace". Strings containing "whitespace" can be delimited by matching single quotes, double quotes, or parentheses: -a 'hello world!', -a "I don't know", or -a (a, b, c). |
| CLI_IPADDR | IPv4 or MAC address. |
The following is the list of options allowed with the "usr1_cli()" example in tcpdata.c
struct cli_parm user1_parms[] = {
{ 'a', CLI_IPADDR }, /* parameter of type IPv4 address */
{ 'b', CLI_NONE }, /* parameter with no <argument> */
{ 'i', CLI_INT }, /* parameter of type integer */
{ 's', CLI_STRING }, /* parameter of type string */
{ 'u', CLI_UINT }, /* parameter of type unsigned integer */
};
The CLI module is responsible for parsing a command line and calling the command's execution function.
The command line parser scans the command line to find the command name. The command parser then searches the installed menus, looking for a match; names are not case-sensitive. Command names can be abbreviated to the first 'N' characters of the name, as long as the name is still unique. Command names must be minimum of 3 characters.
If the command is found, the corresponding cli_cmd and cli_parm structures are used to parse and validate the command parameters. The parameter information is stored in the CLI Context. A parameter may appear at most once in a command line and must be of the correct type. If a parameter needs to support multiple types, for example a device name string or a device number, the CLI_STRING type can be used and parameter validation can be deferred to the command's execution function.
The command parser recognizes the special symbols, '?' and '-?' as "help" flags. Entering a "help" flag as part of a command line causes the command's description and syntax to be displayed on the output device. If the command was successfully parsed, the command's execution function will then be called. The function can test if "help" was entered and take appropriate action, such as displaying addition "help" text and/or not executing the command.
Note that the command line is modified during the command parsing process. Commands that are stored in read-only memory, they must be copied into a writable memory buffer before they can be parsed and executed.
The CLI command parser finds the command's "cli_cmd" structure in the installed menus. The structure includes a pointer to the function to be called to execute the command. The function prototype for any command's execution function is:
int commandname(void *ctx);
The macros below, defined in embcli.h, can be used to access the command's parameters. The use of these macros is shown in the user1_cli() example in tcpdata.c
| CLI_HELP(ctx) | Returns TRUE if either '?' or '-?' was entered as part of the command line. Otherwise, it returns FALSE. |
| CLI_COUNT(ctx) | Returns an integer value representing the number of parameters that were present in the command line. The "help" symbols are not included in the count. |
| CLI_DEFINED(ctx,c) | Return TRUE if the command line included a '-<c>' parameter. Otherwise, it returns FALSE. |
| CLI_VALUE(ctx,c) | Returns the value of the '-<c>' parameter. The value must be cast into the type of the parameter. For example,
if (CLI_DEFINED(ctx, 'p') port = (uint32_t)(CLI_VALUE(ctx, 'p')); else port = MY_DEFAULT_PORT_NUMBER; |
The type for each CLI parameter type was shown in the table in the Commands and Parameters section above.
The CLI_DEFINED() macro should be used to test for the presence of a parameter before using CLI_VALUE() to get the its value.
When a parameter of type CLI_IPADDR is parsed, the information is stored in a cli_addr structure defined by:
struct cli_addr {
int type; /* CLI_IPV4 or CLI_MAC */
uint8_t addr[8]; /* IPv4/MAC address (network-order) */
}
The bytes of the IP address are stored in network byte-order. The "type" field of the structure can be tested to determine if a 32-bit IPv4 address or a MAC address was entered in the command line.
If the embedded system has a console then it can call printf() to output a message to the user.
When the command's execution function has completed its processing, it returns an error code indicating the success or failure of the command. This error code is returned to the caller of cli_command() CLI error codes are defined in embcli.h.
Name
help - display information about a command
Syntax
help [-m STRING] [-c STRING]
Parameters
-m | Menu group name |
-c | Command name |
Description
This command provides helpful information about the CLI commands. If no parameters are entered, the list of available menu groups and the commands within each menu group is displayed. If a menu group is specified, information about the menu group and its commands are displayed. If a command is specified, information about the command is displayed. If the command name is a present in more than one menu group, the menu group name must also be specified to remove any ambiguity.
Notes/Status
"help -m foo -c bar" is equivalent to "foo bar ?"."?" is equivalent to entering "help".arp
arp - Display ARP statistics
Syntax
arp [-z STRING]
Parameters
-z | Reset the ARP statistics associated with STRING to zero. STRING can be either an interface name (e.g. "nd0") or an IP address. |
Description
This command displays the ARP table and the ARP statistics.
If '-z STRING' is specified, the statistics are reset to zero after they are displayed.
Name
dhcstat - Display DHCP/auto-configuration-related information
Syntax
dhcstat
Parameters
None.
Description
This command displays the status of the DHCP, auto-configuration, and UPNP state machines.
Name
iface - Display network interface information
Syntax
iface [-i UINT [-m UINT]]
Parameters
-i | Network Interface number. |
-m | The maximum transmission unit of a Network Interface. |
Description
This command displays information about the specified Network Interface.
If '-i' is not specified, the list of available Network Interfaces
is displayed.
The value of the '-m' is used to set the maximum transmission
unit of the selected interface. Valid values are 128 to 65535. Care must be
taken when setting the value to ensure that the value matches the capabilities
of the underlying hardware.
Notes/Status
Name
linkstats - Display link-specific information
Syntax
linkstats -i INT
Parameters
-i | Network Interface number. |
Description
This command displays Link information for the specified Network Interface. The Link information is device-specific, and is provided by the implementor of the Network Interface device driver.
Notes/Status
Name
netstat - display operational statistics
Syntax
netstat {-c [-p <protocol>]} -m -q {-s [-p <protocol>]}
Parameters
-c | display status information about TCP or UDP sockets. |
-m | display status information about mbufs. |
-p | specify network protocol (ICMP ("icmp"), IP ("ip"), TCP ("tcp"), and UDP ("udp"")) for which information is being requested. |
-q | display status information about the TCP/IP stack's receive queue. |
-s | display statistics for specified network protocol. |
Description
This command displays status information for various network protocols or modules.
Notes/Status
Name
nslookup - Find the IP address of a domain name
Syntax
nslookup -a STRING
Parameters
-a | Display the IPv4 address(es) of the domain name |
Description
This command calls DNS servers or relies on the stack's cache to retrieve the IP address records for a domain name, such as "www.iniche.com."
Notes/Status
setdnssrv command can be used to initialize the DNS Server addresses used in the DNS query.Name
ping - Send ICMP requests
Syntax
ping -a <IP addr> [-n <number of pings>] [ -l <length of packets>]
Parameters
-a | IPv4 address |
-n | Number of pings. Default = 4 |
-l | Length of the Data field in ICMP Echo packet. Default = 56 bytes |
Description
This command sends an ICMP/IPv4 Echo packet. It verifies that the data in the response exactly matches the data in the request. It reports any mismatches.
Notes/Status
queues
queues - Display NicheStack packet queues
Syntax
queues
Parameters
-z | (no parameter). Resets all queues' min and max threshholds to their current values. |
Description
This command displays the current status of various resource queues. These queues include the receive packet queue (rcvdq), free packet queues (cb-#), the free mbuf queue (mfreeq) and the 'inuse' mbuf queue (mbufq).
Sample Output:
-> queues Packet buffer free queues, total packets:120 (99840 bytes) cb-1 Q0128: size:7680, head:00A5A9FC, tail:00A5A96C, len:60, min:57, max:60 cb-2 Q1536: size:92160, head:00A5E784, tail:00A5E73C, len:60, min:52, max:60 mfreeq: head:00A5D82C, tail:00A5D804, len:120, min:118, max:120 mbufq: head:00000000, tail:00000000, len:0, min:0, max:2 rcvdq: head:00000000, tail:00000000, len:0, min:0, max:3
Name
setip - manually set IPv4 address information
Syntax
setip -i INT [-a IPADDR] [-s IPADDR] [-g IPADDR] [-o] [-r] [-e] [-p STRING]
Parameters
-a | Network Interface's IPv4 address. |
-e | Restore previously configured static address (only used in conjunction with the -r option; valid when all address protocols have been deconfigured from the link) |
-g | Network Interface's gateway address. |
-i | Network Interface number. |
-o | Obtain an IPv4 address using the specified protocols (e.g., DHCP, auto-conf) |
-p | Set of address protocols to be used on the link (e.g., "dhcpc", "autoip", "dhcpc,autoip") |
-r | Terminate the use of the specified protocols on link, and relinquish address obtained thru' them |
-s | Network Interface's submask. |
Description
This command configures a Network Interface. The '-i' parameter selects the Network Interface to configure. The user can set the IPv4 address, network submask and gateway IP address. IP address are specified in the format: NNN.NNN.NNN.NNN, where NNN can range from 0 to 255. The format: NNN.NNN, is shorthand for NNN.0.0.NNN.
Changes to the Network Interface configuration are performed immediately; open connections are not flushed or closed. If only the '-i' parameter is specified, the current configuration settings are displayed.
Example
Here are some examples of how to use this command:
##configure a static IPv4 address setip -i 1 -a 10.0.0.112 -s 255.255.255.0 -g 10.0.0.1 ##configure interface #1 to obtain an IPv4 address via DHCP setip -i 1 -o -p dhcpc ##configure interface #1 to obtain an IPv4 address via auto-configuration setip -i 1 -o -p autoip ##configure interface #1 to obtain an IPv4 address via DHCP or auto-configuration ##in this case, the system first attempts to obtain an address via DHCP. If that ##fails, it auto-configures itself with an address in the range from 169.254.1.0 ##to 169.254.254.255. setip -i 1 -o -p dhcpc,autoip ##terminate the use of DHCP on interface #1, and release address obtained via that protocol setip -i 1 -r -p dhcpc ##terminate the use of DHCP and auto-configuration on interface #1, and revert back to a ##previously configured static address setip -i 1 -r -p dhcpc,autoip -e
Notes/Status
Name
setdnssrv - Sets the address of an available DNS server
Syntax
setdnssrv -i <number_of_server> -a <IPv4_server_address> -d
Parameters
-i | Argument of type int, indicating Number of DNS server [1 - n] |
-a | Argument of type IPv4 address, indicating address of server |
-d | Argument indicating that the DNS server residing at the index specified via the -i option is to be deleted |
Description
This command sets one of the DNS server addresses used by the DNS client, and can also be used to add or delete DNS servers from the system configuration.
The maximum number of DNS Serves supported by embTCP is 3.
Name
status - display system status
Syntax
status [-i] [-m] [-q] [-s]
Parameters
-i | Display IP MIB information. |
-m | Display MBuf information. |
-q | Display packet queue information. |
-s | Display system status information. |
Description
This command displays information about various embTCP components.
This product was derived from a portable, flexible and more full-featured product available from InterNiche Technologies, Inc. For more information about this SOURCE CODE PRODUCT, please visit www.iNiche.com or email Sales@iNiche.com.