PREV NEXT INDEX



2. TCP/IP Engine

This chapter describes the main library file, DCRTCP.LIB, which comprises the configuration macros, the data structures and the functions used to initialize and drive TCP/IP. IP version 4 is supported by DCRTCP.LIB.

NOTE Starting with Dynamic C version 7.05, DCRTCP.LIB is a light wrapper around DNS.LIB, IP.LIB, NET.LIB, TCP.LIB and UDP.LIB. No changes are required to existing code.

2.1 TCP/IP Configuration

To run the TCP/IP engine, a host (i.e., the controller board) needs to know its IP address, netmask and default gateway. If DNS (Domain Name System) lookups are needed, a host will also need to know the IP address of the local DNS server.

Media Access Control (MAC) address

Some ISPs require that the user provide them with a MAC address for their device. Run the utility program, /Samples/tcpip/display_mac.c, to display the MAC address of your controller board.

2.1.1 IP Addresses Set Manually

The necessary IP addresses can be set at compile time by defining the configuration macros: MY_IP_ADDRESS, MY_NETMASK, MY_GATEWAY and MY_NAMESERVER. At runtime, the configuration functions, tcp_config(), sethostid() and sethostname() can override the configuration macros.

2.1.2 IP Addresses Set Dynamically

The library BOOTP.LIB allows a target board to be a BOOTP or DHCP client. The protocol used depends on what type of server is installed on the local network. BOOTP and DHCP servers are usually centrally located on a local network and operated by the network administrator. Note that initialization may take longer when using DHCP as opposed to static configuration, but this depends on your server.

Both protocols allow a number of configuration parameters to be sent to the client, including:

To use these protocols, include:


#define USE_DHCP
#use DCRTCP.LIB

in your program.

BOOTP assigns permanent IP addresses. DHCP can "lease" an IP address to a host, i.e., assign the IP address for a limited amount of time.

2.1.2.1 BOOTP/DHCP Control Macros

Various macros control the use of DHCP. Apart from setting these macros before '#use dcrtcp.lib', there is typically very little additional work that needs to be done to use DHCP/BOOTP services. Most of the work is done automatically when you call sock_init() to initialize TCP/IP. There are more control macros available than what are listed here. Please look at the beginning of the file /lib/tcpip/bootp.lib for more information.

USE_DHCP

If this macro is defined, the target uses BOOTP and/or DHCP to configure the required parameters. If USE_DHCP is not defined, then MY_IP_ADDRESS, MY_NETMASK, MY_GATEWAY and (possibly) MY_NAMESERVER must be defined in the application program.

DHCP_USE_BOOTP

If defined, the target uses the first BOOTP response it gets. If not defined, the target waits for the first DHCP offer and only if none comes in the time specified by _bootptimeout does it accept a BOOTP response (if any). Use of this macro speeds up the boot process, but at the expense of ignoring DHCP offers if there is an eager BOOTP server on the local subnet.

DHCP_CLASS_ID "Rabbit2000-TCPIP:Z-World:Test:1.0.0"

This macro defines a class identifier by which the OEM can identify the type of configuration parameters expected. DHCP servers can use this information to direct the target to the appropriate configuration file. Z-World recommends the standard format: "hardware:vendor:product code:firmware" version.

DHCP_USE_TFTP

If this and USE_DHCP are defined, the library will use the BOOTP filename and server to obtain an arbitrary configuration file that will be accessible in a buffer at physical address _bootpdata, with length, _bootpsize. The global variables, _bootpdone and _bootperror indicate the status of the boot file download. DHCP_USE_TFTP should be defined to the maximum file size that may be downloaded.

DHCP_CLIENT_ID clientid_char_ptr
DHCP_CLIENT_ID_LEN clientid_length

Define a client identifier string. Since the client ID can contain binary data, the length of this string must be specified as well. This string MUST be unique amongst all clients in an administrative domain, thus in practice the client ID must be individually set for each client e.g. via front-panel configuration. It is NOT recommended to program a hard-coded string (as for class ID). Note that RFC2132 recommends that the first byte of the string should be zero if the client ID is not actually the hardware type and address of the client (see next).

DHCP_CLIENT_ID_MAC

If defined, this overrides DHCP_CLIENT_ID, and automatically sets the client ID string to be the hardware type (1 for ethernet) and MAC address, as suggested by RFC2132.

2.1.2.2 BOOTP/DHCP Global Variables

The following list of global variables may be accessed by application code to obtain information about DHCP or BOOTP. These variable are only accessible if USE_DHCP is defined.

_bootpon

Runtime control of whether to perform DHCP/BOOTP. This is initially set to 'true'. It can be set to false before calling sock_init (the function that initializes the TCP/IP engine), causing static configuration to be used. Static configuration uses the values defined for the configuration macros, MY_IP_ADDRESS etc. If BOOTP fails during initialization, this will be reset to 0. If reset, then you can call dhcp_acquire() at some later time.

_survivebootp

Set to one of the following values:

0: If BOOTP/DHCP fails, then a runtime error occurs. This is the default.
1: If BOOTP fails, then use the values in MY_IP_ADDRESS etc. If those macros are not defined, a runtime error occurs.

_dhcphost

IP address of last-used DHCP server (~0UL if none). If _survivebootp is true, then this variable should be checked to see if DHCP/BOOTP was actually used to obtain the lease. If _dhcphost is ~0UL, then the fallback parameters (MY_IP_ADDRESS etc.) were used since no DHCP server responded.

_bootphost

IP address of the last-used BOOTP/TFTP server (~0UL if none). Usually obtained from the siaddr field of the DHCP OFFER/ACK message. This is the default host used if NULL is given for the hostname in the call to tftp_exec(). This is the host that provides the boot file.

_dhcplife, _dhcpt1, _dhcpt2

These variables contain various absolute time values (referenced against SEC_TIMER ) at which certain aspects of the DHCP protocol get activated. _dhcplife is when the current lease expires. If _dhcplife is ~0UL (i.e. 0xFFFFFFFF) then the lease is permanent and the other variables are not used. Otherwise, _dhcpt1 is when the current lease must be renewed by the current DHCP server. _dhcpt2 is when the lease must be re-bound to a possibly different server, if the current server does not respond. In general, _dhcpt1 < _dhcpt2 < _dhcplife. To work out the number of seconds remaining until the current lease expires, use code similar to:

if (_dhcplife == ~0UL)
printf("Lease is permanent\r\n");
else if (_dhcplife > SEC_TIMER)
printf("Remaining lease %lu seconds\r\n",
_dhcplife - SEC_TIMER);
else
printf("Lease is expired\r\n");

_bootptimeout

Number of seconds to wait for a BOOTP or DHCP offer. If there is no response within this time (default 30 sec), then BOOTP is assumed to have failed, and the action specified by _survivebootp will be taken. You can set this variable to a different value before calling sock_init().

_bootpdone

Is set to a non-zero value when TFTP download of the boot file is complete. This variable only exists if DHCP_USE_TFTP is defined. It is set to one of the following values:

0: Download not complete, or boot file not yet known.
1: Boot file download completed (check _bootperror for status).
2: No boot file was specified by the server.

_bootpsize

Indicates how many bytes of the boot file have been downloaded. Only exists if DHCP_USE_TFTP is defined.

_bootpdata

Physical starting address of boot data. The length of this area will be DHCP_USE_TFTP bytes, however, the actual amount of data in the buffer is given by _bootpsize. This variable only exists if DHCP_USE_TFTP is defined and is only valid if _bootpdone is 1. You can access the data using xmem2root() and related functions.

_bootperror

Indicates any error which occurred in a TFTP process. This variable only exists if DHCP_USE_TFTP is defined and is only valid when _bootpdone is 1, in which case _bootperror is set to one of the following values (which are also documented with the tftp_tick() function):

 0: No error.

-1: Error from boot file server, transfer terminated. This usually occurs because the server is not configured properly, and has denied access to the nominated file.

-2: Error, could not contact boot file server or lost contact.

-3: Timed out, transfer terminated.

-4: (not used)

-5: Transfer complete, but truncated because buffer too small to receive the complete file.

2.1.2.3 DHCP Functions

There are two user-callable functions regarding IP address leases. To obtain a lease, call dhcp_acquire(). To relinquish it, call dhcp_release().

2.1.2.4 DHCP Sample Program

The following sample code is a basic TCP/IP program that will initialize the TCP/IP interface, and allow the device to be 'pinged' from another computer on the network. DHCP or BOOTP will be used to obtain IP addresses and other network configuration items. A more extensive sample program is in Samples\tcpip\dhcp.c. It demonstrates other DHCP features, such as releasing and re-acquiring IP addresses and downloading a configuration file.

Program Name: samples/tcpip/dhcp.c

// Main define to cause BOOTP or DHCP to be used.
#define USE_DHCP

/* These values may be used as a fallback if _survivebootp is set true. Otherwise, they will be ignored. Note that in a 'real' application, setting fallbacks as hard-coded addresses would be unwise.*/ 

#define MY_IP_ADDRESS "10.10.6.179" 
#define MY_NETMASK "255.255.255.0"
#define MY_GATEWAY "10.10.6.1"

#memmap xmem
#use dcrtcp.lib

/* Print some of the DHCP or BOOTP parameters received. */ 

void print_results(void){
printf("Network Parameters:\r\n");
printf(" My IP Address = %08lX\r\n", my_ip_addr);
printf(" Netmask = %08lX\r\n", sin_mask);
if (_dhcphost != ~0UL) {
if (_dhcpstate == DHCP_ST_PERMANENT) {
printf(" Permanent lease\r\n");
} else {

         printf("Remaining lease= %ld (sec)\r\n", _dhcplife -SEC_TIMER);

         printf("Renew lease in %ld (sec)\r\n", _dhcpt1 - SEC_TIMER);
}
printf(" DHCP server = %08lX\r\n", _dhcphost);
printf(" Boot server = %08lX\r\n", _bootphost);
}
if (gethostname(NULL,0))
printf(" Host name = %s\r\n", gethostname(NULL,0));
if (getdomainname(NULL,0))
printf(" Domain name = %s\r\n", getdomainname(NULL,0));
}

main(){
_survivebootp = 1; // So we can use fallback addresses
_bootptimeout = 6; // Short timeout for testing
sock_init();
if (_dhcphost != ~0UL)
printf("Lease obtained\r\n");
else {
printf("Lease not obtained. DHCP server may be down.\r\n");
printf("Using fallback parameters...\r\n");
}
print_results();
for (;;)
tcp_tick(NULL);
}

2.1.3 Sizes for TCP/IP I/O Buffers

Starting with Dynamic C version 7.05, TCP and UDP I/O buffers are sized separately using:

Compatibility is maintained with earlier versions of Dynamic C. If SOCK_BUF_SIZE is defined, TCP_BUF_SIZE and UDP_BUF_SIZE will be assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then TCP_BUF_SIZE and UDP_BUF_SIZE will be assigned the value of tcp_MaxBufSize * 2.

2.1.3.1 User-supplied Buffers

Starting with Dynamic C version 7.05, a user can associate their own buffer with a TCP or UDP socket. The memory for the buffer must be allocated by the user. This can be done with xalloc(), which returns a pointer to the buffer. This buffer will be tied to a socket by a call to an extended open function: tcp_extlisten(), tcp_extopen() or udp_extopen(). Each function requires a long pointer to the buffer and its length be passed as parameters.

2.2 TCP Socket Interface

Throughout this manual, the term socket refers to four numbers: the IP addresses and port numbers for both sides of a connection.

With Dynamic C version 6.57, each socket must have an associated tcp_Socket structure of 145 bytes or a udp_Socket structure of 62 bytes. The I/O buffers are in extended memory. For Dynamic C 7.05 these sizes are 132 bytes and 48 bytes, respectively.

For earlier versions of Dynamic C, each socket must have a tcp_Socket data structure that holds the socket state and I/O buffers. These structures are, by default, around 4200 bytes each. The majority of this space is used by the input and output buffers.

2.2.1 Number of Sockets

Starting with Dynamic C version 7.05, there are two macros that define the number of sockets available:

Note that DNS does not need a UDP socket buffer since it manages its own buffer. DHCP and TFTP.LIB, however, each need one UDP socket buffer.

Prior to Dynamic C version 7.05, MAX_SOCKETS defined the number of sockets that could be allocated, not including the socket for DNS lookups. If you use libraries such as HTTP.LIB or FTP_SERVER.LIB, you must provide enough sockets in MAX_SOCKETS for them also.

In Dynamic C 7.05 (and later), if MAX_SOCKETS is defined in an application program, MAX_TCP_SOCKET_BUFFERS will be assigned the value of MAX_SOCKETS.

2.2.2 Passive Open

There are two ways to open a TCP socket, passive and active. To passively open a socket, call tcp_listen(); then wait for someone to contact your device. This type of open is commonly used for Internet servers that listen on a well-known port, like 80 for HTTP (Hypertext Transfer Protocol) servers. You supply tcp_listen() with a pointer to a tcp_Socket data structure, the local port number others will be contacting on your device, and the IP address and port number that are valid for the device. If you want to be able to accept connections from any IP address or any port number, set one or both to zero.

To handle multiple simultaneous connections, each new connection will require its own tcp_Socket and a separate call to tcp_listen(), but using the same local port number (lport value). tcp_listen() will immediately return, and you must poll for the incoming connection. You can manually poll the socket using sock_established().

2.2.3 Active Open

When your Web browser retrieves a page, it actively opens one or more connections to the server's passively opened sockets. To actively open a connection, you call tcp_open(), which uses parameters that are similar to the ones used in tcp_listen(). Supply exact parameters for ina and port, which are the IP address and port number you want to connect to; the lport parameter can be zero, causing an unused local port between 1024 and 65535 to be selected.

If tcp_open() returns zero, no connection was made. This could be due to routing difficulties, such as an inability to resolve the remote computer's hardware address with ARP.

2.2.4 Delay a Connection

To accept a connection request when the resources to actually process the request are not available, use the function tcp_reserveport(). It takes one parameter, the port number where you want to accept connections. When a connection to that port number is requested, the 3-way handshaking is done even if there is not yet a socket available. When replying to the connection request, the window parameter in the TCP header is set to zero, meaning, "I can take no bytes of data at this time." The other side of the connection will wait until the value in the window parameter indicates that data can be sent. Using the companion function, tcp_clearreserve(port number), causes TCP/IP to treat a connection request to the port in the conventional way. The macro USE_RESERVEDPORTS is defined by default. It allows the use of these two functions.

When using tcp_reserveport, the 2MSL (Maximum Segment Lifetime) waiting period for closing a socket is avoided.

2.2.5 TCP Socket Functions

There are many functions that can be applied to an open TCP socket. They fall into three main categories: Control, Status, and I/O.

2.2.5.1 Control Functions for TCP Sockets

These functions change the status of the socket or its I/O buffer.

· sock_abort · sock_flushnext
· sock_close · tcp_listen
· sock_flush · tcp_open

tcp_open() and tcp_listen() have been explained in previous sections.

Call sock_close() to end a connection. This call may not immediately close the connection because it may take some time to send the request to end the connection and receive the acknowledgements. If you want to be sure that the connection is completely closed before continuing, call tcp_tick() with the socket structure's address. When tcp_tick() returns zero, then the socket is completely closed. Please note that if there is data left to be read on the socket, the socket will not completely close.

Call sock_abort() to cancel an open connection. This function will cause a TCP reset to be sent to the other end, and all future packets received on this connection will be ignored.

For performance reasons, data may not be immediately sent from a socket to its destination. If your application requires the data to be sent immediately, you can call sock_flush(). This function will try sending any pending data immediately. If you know ahead of time that data needs to be sent immediately, call sock_flushnext() on the socket. This function will cause the next set of data written to the socket to be sent immediately, and is more efficient than sock_flush().

2.2.5.2 Status Functions for TCP Sockets

These functions return useful information about the status of either a socket or its I/O buffers.

· sock_bytesready · sock_rbused
· sock_dataready · sock_tbleft
· sock_established · sock_tbsize
· sock_rbleft · sock_tbused
· sock_rbsize · tcp_tick

tcp_tick() is the daemon that drives the TCP/IP engine, but it also returns status information. When you supply tcp_tick() with a pointer to a tcp_Socket (a structure that identifies a particular socket), it will first process packets and then check the indicated socket for an established connection. tcp_tick() returns zero when the socket is completely closed. You can use this return value after calling sock_close() to determine if the socket is completely closed.

sock_close(&my_socket);
while(tcp_tick(&my_socket)) {
// you can do other things here while waiting for the socket
// to be completely closed.
}

These status functions can be used to avoid blocking when using sock_write() and some of the other I/O functions, as illustrated in the following code.

This block of code checks to make sure that there is enough room in the buffer before adding data with a blocking function. .

if(sock_tbleft(&my_socket,size)) {
sock_write(&my_socket,buffer,size);
}

This block of code ensures that there is a string terminated with a new line in the buffer, or that the buffer is full before calling sock_gets():

sock_mode(&my_socket,TCP_MODE_ASCII);
if(sock_bytesready(&my_socket) != -1) {
sock_gets(buffer,MAX_BUFFER);
}

2.2.5.3 I/O Functions for TCP Sockets

· sock_fastread · sock_putc
· sock_fastwrite · sock_puts
· sock_getc · sock_read
· sock_gets · sock_write
· sock_preread


There are two modes of reading and writing to TCP sockets: ASCII and binary. By default, a socket is opened in binary mode, but you can change the mode with a call to sock_mode().

When a socket is in ASCII mode, it is assumed that the data is an ASCII stream with record boundaries on the newline characters for some of the functions. This behavior means sock_bytesready() will return 0 only when a complete newline-terminated string is in the buffer or the buffer is full. The sock_puts() function will automatically place a newline character at the end of a string, and the sock_gets() function will strip the newline character.

Do not use sock_gets()in binary mode.

2.3 UDP Socket Interface

The UDP protocol is useful when sending messages where either a lost message does not cause a system failure or is handled by the application. Since UDP is a simple protocol and you have control over the retransmissions, you can decide if you can trade low latency for high reliability.

Broadcast Packets

UDP can send broadcast packets (i.e., to send a packet to a number of computers on the same network). This is accomplished by setting the remote IP address to -1, in either a call to udp_open() or a call to udp_sendto(). When used properly, broadcasts can reduce overall network traffic because information does not have to be duplicated when there are multiple destinations.

Checksums

There is an optional checksum field inside the UDP header. This field verifies the header and the data. This feature can be disabled on a reliable network where the application has the ability to detect transmission errors. Disabling the UDP checksum can increase the performance of UDP packets moving through TCP/IP engine. This feature can be modified by:


sock_mode(s, UDP_MODE_CHK);    // enable checksums
sock_mode(s, UDP_MODE_NOCHK); // disable checksums

The first parameter is a pointer to the socket's data structure, either tcp_Socket or udp_Socket.

In Dynamic C version 7.20, some convenient macros offer a safer, faster alternative to using sock_mode(). They are udp_set_chk(s) and udp_set_nochk(s).

Improved Interface

With Dynamic C version 7.05 there is a redesigned UDP API. The new interface is incompatible with the previous one. Section 2.3.1 covers the new interface and Section 2.3.2 covers the previous one.

2.3.1 Dynamic C 7.05 (and later)

This UDP interface is a record service. It receives distinct datagrams and passes them as such to the user program. The socket I/O functions available for TCP sockets will not work for UDP sockets.

See Section 2.3.3 for information on porting a program to the new UDP interface.

2.3.1.1 Control Functions for UDP Sockets

These functions change the status of the socket or its I/O buffer.

· sock_flush · udp_close
· sock_flushnext · udp_open

2.3.1.2 I/O Functions for UDP Sockets

These functions handle datagram-at-a-time I/O:

· udp_recv · udp_send
· udp_recvfrom · udp_sendto

The write function, udp_sendto(), allows the remote IP address and port number to be specified. The read function, udp_recvfrom(), identifies the IP address and port number of the host that sent the datagram. There is no longer a UDP read function that blocks until data is ready.

2.3.1.3 Status Function for UDP Sockets

These functions return useful information about the status of either a socket or its I/O buffers.

· sock_bytesready · sock_rbused
· sock_dataready · sock_tbleft
· sock_established · sock_tbsize
· sock_rbleft · sock_tbused
· sock_rbsize · tcp_tick

For a udp socket, sock_bytesready() returns the number of bytes in the next datagram in the socket buffer, or -1 if no datagrams are waiting. Note that a return of 0 is valid, since a datagram can have 0 bytes of data.

2.3.2 UDP Interface Prior to Dynamic C 7.05

This interface is basically the TCP socket interface with some additional functions for simulating a record service. Some of the TCP socket functions work differently for UDP because of its connectionless state. The descriptions for the applicable functions details these differences.

2.3.2.1 I/O Functions for UDP Sockets

Prior to Dynamic C 7.05, the functions that handle UDP socket I/O are mostly the same functions that handle TCP socket I/O.

· sock_fastread · sock_read
· sock_fastwrite · sock_recv
· sock_getc · sock_recv_from
· sock_gets · sock_recv_init
· sock_preread · sock_write
· sock_putc · udp_close
· sock_puts · udp_open

Notice that there are three additional I/O functions that are only available for use with UDP sockets: sock_recv(), sock_recv_from() and sock_recv_init(). The status and control functions that are available for TCP sockets also work for UDP sockets, with the exception of the open functions, tcp_listen() and tcp_open().

2.3.2.2 Opening and Closing a UDP Socket

udp_open() takes a remote IP address and a remote port number. If they are set to a specific value, all incoming and outgoing packets are filtered on that value (i.e., you talk only to the one remote address).

If the remote IP address is set to -1, the UDP socket receives packets from any valid remote address, and outgoing packets are broadcast. If the remote IP address is set to 0, no outgoing packets may be sent until a packet has been received. This first packet completes the socket, filling in the remote IP address and port number with the return address of the incoming packet. Multiple sockets can be opened on the same local port, with the remote address set to 0, to accept multiple incoming connections from separate remote hosts. When you are done communicating on a socket that was started with a 0 IP address, you can close it with sock_close() and reopen to make it ready for another source.

2.3.2.3 Writing to a UDP Socket

Prior to Dynamic C 7.05, the normal socket functions used for writing to a TCP socket will work for a UDP socket, but since UDP is a significantly different service, the result could be different. Each atomic write--sock_putc(), sock_puts(), sock_write(), or sock_fastwrite()--places its data into a single UDP packet. Since UDP does not guarantee delivery or ordering of packets, the data received may be different either in order or content than the data sent. Packets may also be duplicated if they cross any gateways. A duplicate packet may be received well after the original.

2.3.2.4 Reading From a UDP Socket

There are two ways to read UDP packets prior to Dynamic C 7.05. The first method uses the same read functions that are used for TCP: sock_getc(), sock_gets(), sock_read(), and sock_fastread(). These functions will read the data as it came into the socket, which is not necessarily the data that was written to the socket.

The second mode of operation for reading uses the sock_recv_init(), sock_recv(), and sock_recv_from() functions. The sock_recv_init() function installs a large buffer area that gets divided into smaller buffers. Whenever a datagram arrives, it is stuffed into one of these new buffers. The sock_recv() and sock_recv_from() functions scan these buffers. After calling sock_recv_init on the socket, you should not use sock_getc(), sock_read(), or sock_fastread().

The sock_recv() function scans the buffers for any datagrams received by that socket. If there is a datagram, the length is returned and the user buffer is filled, otherwise sock_recv() returns zero.

The sock_recv_from() function works like sock_recv(), but it allows you to record the IP address where the datagram originated. If you want to reply, you can open a new UDP socket with the IP address modified by sock_recv_from().

2.3.3 Porting Programs from the older UDP API to the new UDP API

To update applications written with the older-style UDP API, use the mapping information in the following table.

UDP API prior to Dynamic C 7.05 UDP API starting with Dynamic C 7.05

MAX_SOCKETS

MAX_UDP_SOCKET_BUFFERS and MAX_TCP_SOCKET_BUFFERS

SOCK_BUF_SIZE

UDP_BUF_SIZE and TCP_BUF_SIZE

udp_open()

udp_open()

sock_write(), sock_fastwrite()

udp_send() or udp_sendto()

sock_read()(blocking function)

udp_recv() or udp_recvfrom() (nonblocking functions)

sock_fastread()

udp_recv() or udp_recvfrom()

sock_recv_init()

udp_extopen() (to specify your own buffer)

sock_recv()

udp_recv()

sock_recv_from()

udp_recvfrom()

sock_close()

sock_close() or udp_close()

sock_bytesready()

sock_bytesready()

sock_dataready()

sock_dataready()


2.4 DNS Lookups

Starting with Dynamic C 7.05, non-blocking DNS lookups are supported. Prior to DC 7.05, there was only the blocking function, resolve(). Compatibility has been preserved for resolve(), MAX_DOMAIN_LENGTH , and DISABLE_DNS.

The application program has to do two things to resolve a host name:

  1. Call resolve_name_start() to start the process.
  2. Call resolve_name_check() to check for a response.

Call resolve_cancel()to cancel a pending lookup.

2.4.1 Configuration Macros for DNS Lookups

DISABLE_DNS

If this macro is defined, DNS lookups will not be done. The DNS subsystem will not be compiled in, saving some code space and memory.

DNS_MAX_RESOLVES

4 by default. This is the maximum number of concurrent DNS queries. It specifies the size of an internal table that is allocated in xmem.

DNS_MAX_NAME

64 by default. Specifies the maximum size in bytes of a host name that can be resolved. This number includes any appended default domain and the NULL-terminator. Backwards compatibility exists for the MAX_DOMAIN_LENGTH macro. Its value will be overridden with the value DNS_MAX_NAME if it is defined.

For temporary storage, a variable of this size must be placed on the stack in DNS processing. Normally, this is not a problem. However, for µC/OS-II with a small stack and a large value for DNS_MAX_NAME, this could be an issue.

DNS_MAX_DATAGRAM_SIZE

512 by default. Specifies the maximum length in bytes of a DNS datagram that can be sent or received. A root data buffer of this size is allocated for DNS support.

DNS_RETRY_TIMEOUT

2000 by default. Specifies the number of milliseconds to wait before retrying a DNS request. If a request to a nameserver times out, then the next nameserver is tried. If that times out, then the next one is tried, in order, until it wraps around to the first nameserver again (or runs out of retries).

DNS_NUMBER_RETRIES

2 by default. Specifies the number of times a request will be retried after an error or a timeout. The first attempt does not constitute a retry. A retry only occurs when a request has timed out, or when a nameserver returns an unintelligible response. That is, if a host name is looked up and the nameserver reports that it does not exist and then the DNS resolver tries the same host name with or without the default domain, that does not constitute a retry.

DNS_MIN_KEEP_COMPLETED

10000 by default. Specifies the number of milliseconds a completed request is guaranteed to be valid for resolve_name_check(). After this time, the entry in the internal table corresponding to this request can be reused for a subsequent request.

DNS_SOCK_BUF_SIZE

1024 by default. Specifies the size in bytes of an xmem buffer for the DNS socket. Note that this means that the DNS socket does not use a buffer from the socket buffer pool.

2.5 Skeleton Program

The following program is a general outline for a Dynamic C TCP/IP program. The first couple of defines set up the default IP configuration information. The "memmap" line causes the program to compile as much code as it can in the extended code window. The "use" line causes the compiler to compile in the Dynamic C TCP/IP code using the configuration data provided above it.

Program Name: /samples/tcpip/icmp/pingme.c

/*
* You must change the following values to whatever
* your local IP address, netmask, and gateway are.
* Contact your network administrator for these numbers.
*/

#define MY_IP_ADDRESS "10.10.6.101"
#define MY_NETMASK "255.255.255.0"
#define MY_GATEWAY "10.10.6.19"

#memmap xmem
#use dcrtcp.lib

main() {
sock_init();
for (;;) {
tcp_tick(NULL);
}
}

To run this program, start Dynamic C and open the SAMPLES\TCPIP\ICMP\PINGME.C file. Edit the MY_IP_ADDRESS, MY_NETMASK, and MY_GATEWAY macros to reflect the appropriate values for your device. Run the program and try to run ping 10.10.6.101 from a command line on a computer on the same physical network, replacing 10.10.6.101 with your value for MY_IP_ADDRESS.

2.5.1 TCP/IP Stack Initialization

The main() function first initializes the TCP/IP stack with a call to sock_init(). This call initializes internal data structures and enables the Ethernet chip, which will take a couple of seconds with the RealTek chip. At this point, the TCP/IP engine is ready to handle incoming packets.

2.5.2 Packet Processing

Incoming packets are processed whenever tcp_tick() is called. The user-callable functions that call tcp_tick() are: tcp_open, udp_open, sock_read, sock_write, sock_close, and sock_abort. Some of the higher-level protocols, e.g. HTTP.LIB, will call tcp_tick() automatically.

It is a good practice to make sure that tcp_tick() is called periodically in your program to insure that the TCP/IP engine has had a chance to process packets. A rule of thumb is to call tcp_tick() around 10 times per second, although slower or faster call rates should also work. The Ethernet interface chip has a large buffer memory, and TCP/IP is adaptive to the data rates that both end of the connection can handle; thus the system will generally keep working over a wide variety of tick rates.

2.5.3 TCP/IP Daemon Computing Time

The computing time consumed by each call to tcp_tick() varies. Rough numbers are less than a millisecond if there is nothing to do, tens of milliseconds for typical packet processing, and hundreds of milliseconds under exceptional circumstances.

2.6 State-Based Program Design

An efficient design strategy is to create a state machine within a function and pass the socket's data structure as a function parameter. This method allows you to handle multiple sockets without the services of a multitasking kernel. This is the way the HTTP.LIB functions are organized. Many of the common Internet protocols fit well into this state machine model.

The general states are:

An example of state-based programming is SAMPLES\TCPIP\STATE.C. This program is a basic Web server that should work with most browsers. It allows a single connection at a time, but can be extended to allow multiple connections.

2.6.1 Blocking vs. Non-Blocking

There is a choice between blocking and non-blocking functions when doing socket I/O.

2.6.1.1 Non-Blocking Functions

The sock_fastread() and sock_preread() functions read all available data in the buffers, and return immediately. Similarly, the sock_fastwrite() function fills the buffers and returns the number of characters that were written. When using these functions, you must ensure that all of the data were written completely.

offset=0;
while(offset<length) {
bytes_written=sock_fastwrite(&socket,buffer+offset,length-offset);
if(bytes_written<0) {
// error handling
}
offset+=bytes_written;
}

2.6.1.2 Blocking Functions

The other functions (sock_getc(), sock_gets(), sock_putc(), sock_puts(), sock_read() and sock_write()) do not return until they have completed or there is an error. If it is important to avoid blocking, you can check the conditions of an operation to insure that it will not block.

sock_mode(socket,TCP_MODE_ASCII);
// ...
if (sock_bytesready(&my_socket) != -1){
sock_gets(buffer,MAX_BUFFER);
}

In this case sock_gets() will not block because it will be called only when there is a complete new line terminated record to read.

2.7 Multitasking and TCP/IP

Dynamic C's TCP/IP implementation is compatible with both µC/OS-II and with the language constructs that implement cooperative multitasking: costatements and cofunctions. Note that TCP/IP is not compatible with the slice statement.

2.7.1 µC/OS-II

The TCP/IP engine may be used with the µC/OS-II real-time kernel. The line


#use ucos2.lib

must appear before the line


#use dcrtcp.lib

in the application program. Also be sure to call OSInit() before calling sock_init().

Dynamic C version 7.05 and later requires the macro MAX_SOCKET_LOCKS for µC/OS-II support. If it is not defined, it will default to MAX_TCP_SOCKET_BUFFERS + TOTAL_UDP_SOCKET_BUFFERS (which is MAX_UDP_SOCKET_BUFFERS + 1 if there are DNS lookups).

If buffers have been xalloc'd for socket I/O, they should be accounted for in MAX_SOCKET_LOCKS.

2.7.2 Cooperative Multitasking

The following program demonstrates the use of multiple TCP sockets with costatements.

Program Name: costate_tcp.c

#define MY_IP_ADDRESS "10.10.6.11"
#define MY_NETMASK "255.255.255.0"
#define MY_GATEWAY "10.10.6.1"

#define PORT1 8888
#define PORT2 8889

#define SOCK_BUF_SIZE 2048
#define MAX_SOCKETS 2


#memmap xmem
#use "dcrtcp.lib"

tcp_Socket Socket_1;
tcp_Socket Socket_2;


#define MAX_BUFSIZE 512
char buf1[MAX_BUFSIZE], buf2[MAX_BUFSIZE];


// The function that actually does the TCP work
cofunc int basic_tcp[2](tcp_Socket *s, int port, char *buf){
auto int length, space_avaliable;

tcp_listen(s, port, 0, 0, NULL, 0);

   
// wait for a connection
while((-1 == sock_bytesready(s)) && (0 == sock_established(s)))
// give other tasks time to do things while we are waiting
yield;
while(sock_established(s)) {
space_avaliable = sock_tbleft(s);
// limit transfer size to MAX_BUFSIZE, leave room for '\0'
if(space_avaliable > (MAX_BUFSIZE-1))
space_avaliable = (MAX_BUFSIZE-1);
// get some data
length = sock_fastread(s, buf, space_avaliable);

      
if(length > 0) {         // did we receive any data?
buf[length] = '\0';   // print it to the stdio window
printf("%s",buf);
// send it back out to the user's telnet session
// sock_fastwrite will work-we verified the space beforehand
sock_fastwrite(s, buf, length);
}
yield;                  // give other tasks time to run
}
sock_close(s);
return 1;
}

Program Name: costate_tcp.c (continued)

main() {
sock_init();
while (1) {
costate {
// Go do the TCP/IP part, on the first socket
wfd basic_tcp[0](&Socket_1, PORT1, buf1);
}
costate {
// Go do the TCP/IP part, on the second socet
wfd basic_tcp[1](&Socket_2, PORT2, buf2);
}
costate {
// drive the tcp stack
tcp_tick(NULL);
}
costate {
// Can insert application code here!
waitfor(DelayMs(100));
}
}
}

2.8 Function Reference

This section contains descriptions for all user-callable functions in DCRTCP.LIB. Starting with Dynamic C 7.05, DCRTCP.LIB is a light wrapper around DNS.LIB, IP.LIB, NET.LIB, TCP.LIB and UDP.LIB. This update requires no changes to existing code.

Descriptions for select user-callable functions in ARP.LIB, ICMP.LIB, BSDNAME.LIB and XMEM.LIB are also included here. Note that ARP.LIB, ICMP.LIB and BSDNAME.LIB are automatically #use'd from DCRTCP.LIB.


arpcache_create



ATHandle arpcache_create(longword ipaddr)

Description

Create a new entry in the ARP cache table for the specified IP address. If a matching entry for that address already exists, then that entry is returned. Otherwise, a new entry is initialized and returned. If a new entry is created, then an old entry may need to be purged. If this is not possible, then ATH_NOENTRIES is returned.

Parameter

ipaddr

IP address of entry.

Return Value

Positive value: success.
ATH_NOENTRIES: no space is available in the table, and none of the entries could be purged because they were all marked as permanent or router entries.

Library

ARP.LIB


arpcache_flush



ATHandle arpcache_flush(ATHandle ath);

Description

Mark an ARP cache table entry for flushing. This means that the given table entry will be the first entry to be re-used for a different IP address, if necessary. Any entry (including permanent and router entries) may be flushed except for the broadcast entry.

Parameter

ath

ARP table handle obtained from e.g. arpcache_search().

Return Value

Positive value: success.
ATH_UNUSED: the table entry was unused.
ATH_INVALID: the ath parameter was not a valid handle.
ATH_OBSOLETE: the given handle was valid, but obsoleted by a more recent entry. No change made.

Library

ARP.LIB


arpcache_hwa



ATHandle arpcache_hwa(ATHandle ath, byte * hwa);

Description

Copy the ethernet (hardware) address from the given ARP cache table entry into the specified area.

Parameters

ath

ARP cache table entry.

hwa

Address of where to store the hardware address (6 bytes).

Return Value

Positive value: handle to the entry.
ATH_UNUSED: the table entry was unused.
ATH_INVALID: the ath parameter was not a valid handle.
ATH_OBSOLETE: the given handle was valid, but obsoleted by a more recent entry. No change made.

Library

ARP.LIB


arpcache_load



ATHandle arpcache_load(ATHandle ath, byte * hwa, byte iface, word flags, byte router_used);

Description

Load an entry in the ARP cache table. The entry must have been created using arpcache_create(), or be an existing valid entry located via arpcache_search().

This function is primarily intended for internal use by the ARP library, although advanced applications could also use it. Most applications should not need to call this function directly.

Parameters

ath

Handle for the entry.

hwa

Hardware (ethernet) address, or NULL. Pass NULL if the current hardware address is not to be changed.

iface

Interface to use (IF_DEFAULT to use default, or not change current setting).

flags

Flags for entry: one or more of the following values, OR'd together:

· ATE_PERMANENT: permanent entry
· ATE_RESOLVING: initiate network resolve for this entry (hwa is ignored if this flag is set)
· ATE_RESOLVED: this entry now resolved
· ATE_ROUTER_ENT: this is a router entry
· ATE_FLUSH: mark this entry for flush
· ATE_VOLATILE: set short timeout for this entry
· ATE_ROUTER_HOP: this entry uses the specified router as the first hop. hwa ignored.
· ATE_REDIRECTED: this entry redirected by ICMP.

Only one of ATE_ROUTER_ENT or ATE_ROUTER_HOP should be set. For either of these, the next parameter indicates the router table entry to use.

Only one of ATE_RESOLVING or ATE_RESOLVED should be set.

router_used

Router table entry. Only used if one of ATE_ROUTER_ENT or ATE_ROUTER_HOP is set in the flags parameter.



Return Value

Positive value: success.

ATH_NOROUTER: the specified router entry number is invalid. This can be because the router_used parameter is bad, or because the router entry has a mismatching ATH.

ATH_INVALID: invalid table handle passed (or unused entry).

ATH_OBSOLETE: the given handle was valid, but obsoleted by a more recent entry. No change made.

Library

ARP.LIB


arpcache_search



ATHandle arpcache_search(longword ipaddr, int virt);

Description

Return handle which refers to the ARP cache table entry for the given IP address. This does not do any resolving. It only consults the existing cache entries. The returned handle is guaranteed to be valid at least until the next call to tcp_tick(). Usually the handle will be valid for considerably longer, however it is possible for the handle to become obsolete if the cache entry is re-used for a different address. The caller should be able to deal with this possibility. The entry returned for the broadcast address is guaranteed to be permanent.

Parameters

ipaddr

IP address to locate in the cache. This may be -1L to locate the broadcast entry or our own IP address to return the "loopback" entry.

virt

0: do not return the broadcast or loopback entries.

1: allow the broadcast or loopback entries.

Return Value

Positive value: handle to the entry.
ATH_NOTFOUND: no entry exists for the given IP address.

Library

ARP.LIB


_arp_resolve



int _arp_resolve(longword ina, eth_address *ethap, int nowait);

Description

Gets the Ethernet address for the given IP address. This function is deprecated starting in Dynamic C 7.20.

Parameters

ina

The IP address to resolve to an Ethernet address.

ethap

The buffer to hold the Ethernet address.

nowait

If 0, return within 750 ms; else if !0 wait up to 5 seconds trying to resolve the address.

Return value

1: Success.
0: Failure.

Library

ARP.LIB


arpresolve_check



ATHandle arpresolve_check(ATHandle ath, longword ipaddr)

Description

Check up on status of resolve process initiated by arpresolve_start(). This function should be called regularly to ensure that an ARP table handle is pointing to the correct entry, and that the entry is still current.

This caller must call tcp_tick() if spinning on this function.

Parameters

ath

ARP Table Handle obtained from arpresolve_start().

ipaddr

IP address specified to arpresolve_start(). If this is zero, no check is performed. Otherwise, the ARP table entry is checked to see that it is the correct entry for the specified IP address.

Return Value

Positive value: completed successfully. The return value will be the same as the ath parameter.
ATH_AGAIN: not yet completed, try again later.
ATH_FAILED: completed in error. Address cannot be resolved because of a network configuration problem.
ATH_TIMEDOUT: resolve timed out. No response from addressee within the configured time limit.
ATH_INVALID: the ath parameter was not a valid handle|.
ATH_OBSOLETE: the given handle was valid, but obsoleted by a more recent entry. Restart using arpresolve_start().
ATH_MISMATCH: the ipaddr parameter was not zero, and the IP address does not match the table entry.

Library

ARP.LIB


arpresolve_ipaddr



longword arpresolve_ipaddr(ATHandle ath)

Description

Given an ARP table handle, return the IP address of the corresponding table entry.

Parameter

ath

ARP Table Handle obtained from e.g. router_for().

Return Value

0: An error occurred, such as an invalid or obsolete handle.
0xFFFFFFFF: The handle refers to either the broadcast address, or to a point-to-point entry whose IP address is not defined.
Else: An IP address. This may be 127.0.0.1 for the loopback entry.

Library

ARP.LIB


arpresolve_start



ATHandle arpresolve_start(longword ipaddr);

Description

Start resolve process for the given IP address. This may return immediately if the IP address is in the ARP cache table and still valid. Otherwise, if the IP address is on the local subnet then an ARP resolve request is issued through the appropriate interface. If the address is not on the local subnet, then a router table entry is used and no network activity is necessary (unless the router itself is not resolved, in which case its resolution commences).

Parameter

ipaddr

IP address of host whose hardware address is to be resolved.

Return Value

Positive value: success. The value is actually the ATH of the ARP cache table entry which is (or will be) used. This value should be passed to subsequent calls to arpresolve_check().

ATH_NOENTRIES: no space is available in the table, and none of the entries could be purged, because they were all marked as permanent or router entries.

ATH_NOROUTER: no router ("gateway") is configured for the specified address, which is not on the local subnet.

Library

ARP.LIB


_chk_ping



longword _chk_ping( longword host_ip, longword *sequence_number); 

Description

Checks for any outstanding ping replies from host. _chk_ping should be called frequently with a host IP address. If an appropriate packet is found from that host IP address, the sequence number is returned through *sequence_number. The time difference between our request and their response is returned in milliseconds.

Parameters

host_ip

IP address to receive ping reply from.

sequence_number

Sequence number of reply.

Return value

Time in milliseconds from the ping request to the host's ping reply.
If _chk_ping returns 0xffffffffL, there were no ping receipts on this current call.

Library

ICMP.LIB

See Also

_ping, _send_ping


dhcp_acquire



int dhcp_acquire( void );

Description

This function acquires a DHCP lease that has not yet been obtained, or has expired, or was relinquished using dhcp_release(). Normally, DHCP leases are renewed automatically, however if the DHCP server is down for an extended period then it might not be possible to renew the lease in time, in which case the lease expires and TCP/IP should not be used. When the lease expires, tcp_tick() will return 0, and the global variable for the IP address will be reset to 0. At some later time, this function can be called to try to obtain an IP address.

This function blocks until the lease is renewed, or the process times out.

Return value

 0: OK, lease was not expired, or an IP address lease was acquired with the same
       IP address as previously obtained.

-1: An error occurred, no IP address is available. TCP/IP functionality is thus not
       available. Usual causes of an error are timeouts because a DHCP or BOOTP server
       is not available within the timeout specified by the global variable
        _bootptimeout (default 30 seconds).

 1: Lease was re-acquired, however the IP address differs from the one previously
       obtained. All existing sockets must be re-opened. Normally, DHCP servers are
       careful to reassign the same IP address previously used by the client, however this
       is sometimes not possible.

Library

BOOTP.LIB


dhcp_get_timezone



 int dhcp_get_timezone( long * seconds );

Description

This function returns the time zone offset provided by the DHCP server, if any, or uses the fallback time zone defined by the TIMEZONE macro. Note that TIMEZONE is expressed in hours, whereas the return result is in seconds.

Parameters

seconds

Pointer to result longword. If the return value is 0 (OK), then this will be set to the number of seconds offset from Coordinated Universal Time (UTC). The value will be negative for west; positive for east of Greenwich. If the return value is -1, then the result will be set using the hard-coded value from the macro TIMEZONE (converted to seconds by multiplying by 3600), or zero if this macro is not defined.

Return Value

 0: Time zone obtained from DHCP.
-1: Time zone not valid, or not yet obtained, or not using DHCP.

Library

BOOTP.LIB


dhcp_release



int dhcp_release( void );

Description

This function relinquishes a lease obtained from a DHCP server. This allows the server to re-use the IP address that was allocated to this target. After calling this function, the global variable for the IP address is set to 0, and it is not possible to call any other TCP/IP function which requires a valid IP address. Normally, dhcp_release() would be used on networks where only a small number of IP addresses are available, but there are a large number of hosts which need sporadic network access.

This function is non-blocking since it only sends one packet to the DHCP server and expects no response.

Return value

 0: OK, lease was relinquished.

 1: Not released, because an address is currently being acquired, or because a boot file
      (from the BOOTP or DHCP server) is being downloaded, or because some other
      network resource is in use e.g. open TCP socket. Call dhcp_release() again
      after the resource is freed.

-1: Not released, because DHCP was not used to obtain a lease, or no lease was acquired.

Library

BOOTP.LIB


getdomainname



char * getdomainname( char *name, int length );

Description

Gets the current domain name. For example, if the controller's internet address is "test.mynetwork.com" then "mynetwork" is the domain portion of the name.

The domain name can be changed by the setdomainname() function.

Parameters

name

Buffer to place the name.

length

Maximum length of the name, or zero to get a pointer to the internal domain name string. Do not modify this string!

Return value

If length 1: Pointer to name. If length is not long enough to hold the domain name, a NULL string is written to name.

If length = 0: Pointer to internal string containing the domain name. Do not modify this string!

Library

BSDNAME.LIB

See also

setdomainname, gethostname, sethostname, getpeername, getsockname

Example

main() {
sock_init();
printf("Using %s for a domain\n", getdomainname(NULL, 0));
}


gethostid



longword gethostid( void );

Description

Return the IP address of the controller in host format.

Return value

IP address in host format, or zero if not assigned or not valid.

Library

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sethostid

Example

main() {
char buffer[ 512 ];
sock_init();
printf("My IP address is %s\n", inet_ntoa( buffer, gethostid()));
}


gethostname



char * gethostname( char *name, int length );

Description

Gets the host portion of our name. For example if the controller's internet address is "test.mynetwork.com" the host portion of the name would be "test."

The host name can be changed by the sethostname() function.

Parameters

name

Buffer to place the name.

length

Maximum length of the name, or zero for the internal host name buffer. Do not modify this buffer.

Return value

length 1: return name;
length = 0: return internal host name buffer (do not modify!)

Library

BSDNAME.LIB


getpeername



int getpeername( sock_type * s, void * dest, int * len );

Description

Gets the peer's IP address and port information for the specified socket.

Parameters

s

Pointer to the socket.

dest

Pointer to sockaddr to hold the socket information for the remote end of the socket. The data structure is:


typedef struct sockaddr {
word s_type; /* reserved */
word s_port; /* port number, or zero if not connected */
longword s_ip; /* IP address, or zero if not connected */
byte s_spares[6]; /* not used for tcp/ip connections */
};

len

Pointer to the length of sockaddr. A NULL pointer can be used to represent the sizeof(struct sockaddr).

Return value

 0: Success.
-1: Failure.

Library

BSDNAME.LIB

See also

getsockname


getsockname



int getsockname( sock_type * s, void * dest, int * len );

Description

Gets the controller's IP address and port information for a particular socket.

Parameters

s

Pointer to the socket.

dest

Pointer to sockaddr to hold the socket information for the local end of the socket. The data structure is:


typedef struct sockaddr {
word s_type; /* reserved */
word s_port; /* port number, or zero if not connected */
longword s_ip; /* IP address, or zero if not connected */
byte s_spares[6]; /* not used for tcp/ip connections */
};

len

Pointer to the length of sockaddr. A NULL pointer can be used to represent the sizeof(struct sockaddr). BSDNAME.LIB will assume 14 bytes if a NULL pointer is passed.

Return value

 0: Success.
-1: Failure.

Library

BSDNAME.LIB

See also

getpeername


htonl



longword htonl( longword value );

Description

This function converts a host-ordered double word to a network-ordered double word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network-byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.

Parameters

value

Host-ordered double word.

Return value

Host word in network format, e.g. htonl(0x44332211) returns 0x11223344.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

htons, ntohl, ntohs


htons



word htons( word value );

Description

Converts host-ordered word to a network-ordered word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network-byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order within each 16-bit section.

Parameters

value

Host-ordered word.

Return value

Host-ordered word in network-ordered format, e.g. htons(0x1122) returns 0x2211.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

htonl, ntohl, ntohs


inet_addr



longword inet_addr( char * dotted_ip_string );

Description

Converts an IP address from dotted decimal IP format to its binary representation. No check is made as to the validity of the address.

Parameters

dotted_ip_string

Dotted decimal IP string, e.g. "10.10.6.100".

Return value

0: Failure.
Binary representation of dotted_ip_string: Success.

Library

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

inet_ntoa


inet_ntoa



char *inet_ntoa( char *s, longword ip );

Description

Converts a binary IP address to its dotted decimal format, e.g. inet_ntoa(s,0x0a0a0664) returns a pointer to "10.10.6.100".

Parameters

s

Location to place the dotted decimal string. A sufficient buffer size would be 16 bytes.

ip

The IP address to convert.

Return value

Pointer to the dotted decimal string pointed to by s.

Library

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

inet_addr


ntohl



longword ntohl( longword value );

Description

Converts network-ordered long word to host-ordered long word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.

Parameters

value

Network-ordered long word.

Return value

Network-ordered long word in host-ordered format,
e.g. ntohl(0x44332211) returns 0x11223344

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

htons, ntohs, htonl


ntohs



word ntohs( word value );

Description

Converts network-ordered word to host-ordered word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.

Parameters

value

Network-ordered word.

Return value

Network-ordered word in host-ordered format,
e.g. ntohs(0x2211) returns 0x1122

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

htonl, ntohl, htons


paddr



unsigned long paddr(void* pointer);

Description

Converts a logical pointer into its physical address. Use caution when converting address in the E000-FFFF range. This function will return the address based on the XPC on entry.

Parameters

pointer

Pointer to convert.

Return value

Physical address of pointer.

Library

XMEM.LIB


pd_getaddress



void pd_getaddress(int nic, void* buffer);

Description

This function copies the Ethernet address (e.g., MAC address) into the buffer.

Parameters

nic

This parameter is reserved for future expandability and for now should be assigned a value of 0.

buffer

Place to copy address to. Must be at least 6 byes.

Return value

None.

Library

PKTDRV.LIB

Example


main() {
char buf[6];
sock_init();
pd_getaddress(0,buf);

   printf("Your Link Address is:%02x%02x:%02x%02x:%02x%02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);

}


_ping



int _ping( longword host_ip, longword sequence_number );

Description

Generates an ICMP request for host. NOTE: this is a macro that calls _send_ping.

Parameters

host_ip

IP address to send ping.

sequence_number

User-defined sequence number.

Return value

 0: Success.
 1: Failure: unable to resolve hardware address.
-1: Failure: unable to transmit ICMP request.

Library

ICMP.LIB

See also

_chk_ping, _send_ping


psocket



void psocket( void * s );

Description

Given an open UDP or TCP socket, the IP address of the remote host is printed out to the Stdio window in dotted IP format followed by a colon and the decimal port number on that machine. This routine can be useful for debugging your programs.

Parameters

s

Pointer to a socket.

Return value

None.

Library

BSDNAME.LIB


resolve



longword resolve( char *host_string );

Description

Converts a text string, which contains either the dotted IP address or host name, into the longword containing the IP address. In the case of dotted IP, no validity check is made for the address. NOTE: this function blocks. Names are currently limited to 64 characters. If it is necessary to lookup larger names include the following line in the application program:


#define DNS_MAX_NAME <len in chars>.

If DISABLE_DNS has been defined, resolve() will not do DNS lookup.

If you are trying to resolve a host name, you must set up at least one name server. You can set the default name server by defining the MY_NAMESERVER macro at the top of your program. When you call resolve(), it will contact the name server and request the IP address. If there is an error, resolve() will return 0L.

To simply convert dotted IP to longword, see inet_addr().

For a sample program, see the Example Using tcp_open() listed under tcp_open().

Parameters

host_string

Pointer to text string to convert.

Return value

 0: Failure.
!0: The IP address *host_string resolves to.

Library

DNS.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

_arp_resolve, inet_addr, inet_ntoa


resolve_cancel



int resolve_cancel(int handle);

Description

Cancels the resolve request represented by the given handle. If the handle is 0, then this function cancels all outstanding resolve requests.

Parameters

handle

Handle that represents a DNS lookup process, or 0 to cancel all outstanding resolve requests.

Return value

RESOLVE_SUCCESS: The resolve request corresponding to the given handle has been cancelled. The given handle will no longer be valid after this value is returned.

RESOLVE_HANDLENOTVALID: There is no request for the given handle.

RESOLVE_NONAMESERVER: No nameserver has been defined.

Library

DNS.LIB

See also

resolve_name_start, resolve_name_check, resolve


resolve_name_check



int resolve_name_check(int handle, longword* resolved_ip);

Description

Checks if the DNS lookup represented by the given handle has completed. On success, it fills in the resolved IP address in the space pointed to by resolved_ip.

Parameters

handle

Handle that represents a DNS lookup process.

resolved_ip

A pointer to a user-supplied longword where the resolved IP address will be placed.

Return value

RESOLVE_SUCCESS: The address was successfully resolved. The given handle will no longer be valid after this value is returned.

RESOLVE_AGAIN The resolve process has not completed, call this function again.

RESOLVE_FAILED The DNS server responded that the given host name does not exist. The given handle will no longer be valid if RESOLVE_FAILED is returned.

RESOLVE_TIMEDOUT The request has been cancelled because a response from the DNS server was not received before the last timeout expired. The given handle will no longer be valid after this value is returned.

RESOLVE_HANDLENOTVALID There is no DNS lookup occurring for the given handle.

RESOLVE_NONAMESERVER: No nameserver has been defined.

Library

DNS.LIB

See also

resolve_name_start, resolve_cancel, resolve


resolve_name_start



int resolve_name_start(char* hostname);

Description

Starts the process of resolving a host name into an IP address. The given host name is limited to DNS_MAX_NAME characters, which is 64 by default (63 characters + the NULL terminator). If a default domain is to be added, then the two strings together are limited to DNS_MAX_NAME.

If hostname does not contain a '.' then the default domain (MY_DOMAIN) , if provided, is appended to hostname. If hostname with the appended default domain does not exist, hostname is tried by itself. If that also fails, the lookup fails.

If hostname does contain a '.' then hostname is looked up by itself. If it does not exist, the default domain is appended, and that combination is tried. If that also fails, the lookup fails.

If hostname ends with a '.', then the default domain is not appended. The host name is considered "fully qualified." The lookup is attempted without the ending '.' and if that fails no other combinations are attempted.

This function returns a handle that must be used in the subsequent resolve_name_check() and resolve_cancel() functions.

Parameters

hostname

Host name to convert to an IP address

Return value

>0: Handle for calls to resolve_name_check() and resolve_cancel().
RESOLVE_NOENTRIES: Could not start the resolve process because there were no resolve entries free.
RESOLVE_LONGHOSTNAME: The given hostname was too large.
RESOLVE_NONAMESERVER: No nameserver has been defined.

Library

DNS.LIB

See also

resolve_name_check, resolve_cancel, resolve


rip



char * rip( char * string );

Description

Strips newline (\n) and/or carriage return (\r) from a string. Only the first \n and \r characters are replaced with \0s. The resulting string beyond the first \0 character is undefined.

Parameters

string

Pointer to a string.

Return value

Pointer to the modified string.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Example

setmode( s, TCP_MODE_ASCII );
...
sock_puts( s, rip( questionable_string ));

NOTE In ASCII mode sock_puts() adds \n; rip is used to make certain the string does not already have a newline character. Remember, rip modifies the source string, not a copy!

router_add



ATHandle router_add(longword ipaddr, byte iface, longword subnet, longword mask, word flags);

Description

Add a router to the router table. The same router can be added multiple times, with different subnet and mask. Normally, only one entry is needed in order to access non-local subnets: this entry should be specified with a zero mask. The hardware address of the router is not immediately resolved, however this can be done explicitly by calling arpresolve_start() with the same IP address. Otherwise, the router will be resolved only when it first becomes necessary.

Parameters

ipaddr

IP address of the router. This address should be on the local subnet, since non-local routers are not supported.

iface

Interface to use to access this router, or IF_DEFAULT.

subnet

Subnet accessible through this entry.

mask

Subnet mask for this entry.

flags

Flags word: set to zero (non-zero reserved for internal use).

Return Value

Positive value: completed successfully. The return value is the ARP cache table entry for this router.

ATH_NOENTRIES: insufficient space in either the router or ARP cache tables.

Library

ARP.LIB


router_del_all



void router_del_all(void);

Description

Delete all router table entries. This will make any host that is not on the local subnet inaccessible. This function is usually called in preparation for adding a new router entry.

Library

ARP.LIB


router_delete



ATHandle router_delete(longword ipaddr);

Description

Delete a router from the router table. All instances of the router's IP address are deleted, and the ARP cache table entry is flushed.

Parameter

ipaddr

IP address of the router. This address should be on the local subnet, since non-local routers are not supported.

Return Value

Positive value: completed successfully.
ATH_NOTFOUND: specified entry did not exist.

Library

ARP.LIB


router_for



ATHandle router_for(longword ipaddr, byte * router_used, byte * r_iface);

Description

Return the ARP cache table entry corresponding to the router that handles the given IP address. If there is a pre configured router for the given address, it is selected. Otherwise, routers discovered via DHCP or ICMP router discovery are searched, with the highest preference being selected. Failing this, if there is a point-to-point interface, this is selected as the default.

An alternative mode of calling this function is invoked if ipaddr is zero. In this case, the default router for the specified interface (*r_iface) is returned. If r_iface is NULL, then the default interface is assumed:IF_DEFAULT, the only interface supported at present. IF_DEFAULT may refer to the primary ethernet NIC or a PPP connection that uses a serial port or the primary ethernet NIC.

Parameters

ipaddr

IP address of the host which is not on the local subnet.

router_used

If not NULL, the byte at this location is set to the index of the router in the router table.

r_iface

If not NULL, the byte at this location is set to the interface number that can access the router.

Return Value

Positive value: completed successfully.
ATH_NOROUTER: no suitable router found. Either no router is configured, or the given IP address is on the local subnet.

Library

ARP.LIB


router_print



int router_print(byte r)

Description

Print a router table entry, indexed by 'r.' This is for debugging only, since the results are printed to the Dynamic C stdio window. 'r' may be obtained from the router_for() function, by passing &r as the router_used parameter to that function.

If the specified router entry is not in use, nothing is printed and the return value is non-zero. Otherwise, the information is printed and zero returned.

See router_printall() for a description of the output fields printed.

Parameter

r

Router table index. A number from 0 through (ARP_ROUTER_TABLE_SIZE-1).

Return Value

 0: Success, information printed to stdio window.
!0: Entry is not in use.

Library

ARP.LIB

See Also

router_printall


router_printall



int router_printall(void)

Description

Print all router table entries. This is for debugging only, since the results are printed to the Dynamic C stdio window. If no routers exist in the table, nothing is printed and the return value is non-zero.

There are 6 fields for each router entry:

Router Table Entry Field Description of Field
# The entry number.
Flags A list of the following characters:
   P = this entry pre configured
   T = transient entry
   D = added by DHCP/BOOTP
   R = added by ICMP redirect
   ? = router not reachable
   H = router's hardware address resolved
Address Either the router's IP address or an indication that the entry is a point-to-point link.
i/f Interface number.
Net/preference For pre configured entries, indicates the network(s) which are served by this entry (the Mask indicates which bits of the IP address are used to match with the network address). For non-pre configured entries, this is the "preference value" assigned.
Mask/exp(sec) For pre configured entries, the bitmask to apply to IP addresses when matching against the above network. Otherwise, is the expiry time from the present, in seconds, of a transient entry.

Return Value

 0: Success, information printed to stdio window.
!0: No routers in the table.

Library

ARP.LIB


_send_ping



int _send_ping( longword host, longword countnum, byte ttl, byte tos, longword *theid );

Description

Generates an ICMP request for host.

Parameters

host

IP address to send ping.

countnum

User-defined count number.

ttl

Time to live for the packets (hop count). 255 is a standard value for this field. See sock_set_ttl() for details.

tos

Type of service on the packets. See sock_set_tos() for details.

theid

The identifier that was sent out.

Return value

 0: Success.
 1: Failure: unable to resolve hardware address.
-1: Failure: unable to transmit ICMP request.

Library

ICMP.LIB

See also

_chk_ping, _ping, sock_set_ttl, sock_set_tos


setdomainname



char *setdomainname( char *name );

Description

The domain name returned by getdomainname() and used for resolve() is set to the value in the string pointed to by name. Changing the contents of the string after a setdomainname() will change the value of the system domain string. It is not recommended. Instead dedicate a static location for holding the domain name.

setdomainname( NULL ) is an acceptable way to remove any domain name and subsequent resolve calls will not attempt to append a domain name.

Parameters

name

Pointer to string.

Return value

Pointer to string that was passed in.

Library

BSDNAME.LIB

See also

getdomainname, sethostname, gethostname, getpeername, getsockname


sethostid



longword sethostid( longword ip );

Description

This function changes the system's current IP address. Changing this address will disrupt existing TCP or UDP sessions. You should close all sockets before calling this function.

Normally there is no need to call this function. The macro MY_IP_ADDRESS defines an initial IP address for this host, or you can define USE_DHCP to obtain a dynamically assigned address. In either case, it is not recommended to use this function to change the address.

Parameters

ip

New IP address.

Return value

New IP address.

Library

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

gethostid


sethostname



char * sethostname( char *name);

Description

Sets the host portion of our name.

Parameters

name

The new host name.

Return value

Pointer to internal hostname buffer on success, or
NULL on error (if hostname is too long).

Library

BSDNAME.LIB


sock_abort



void sock_abort( void * s );

Description

Close a connection immediately. Under TCP this is done by sending a RST (reset).

Under UDP there is no difference between sock_close() and sock_abort().

Parameters

s

Pointer to a socket.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_close,


sock_bytesready



int sock_bytesready( void * s );

Description

For TCP sockets:

If the socket is in binary mode, sock_bytesready() returns the number of bytes waiting to be read. If there are no bytes waiting, it returns -1.

In ASCII mode, sock_bytesready() returns -1 if there are no bytes waiting to be read or the line that is waiting is incomplete (no line terminating character has been read). The number of bytes waiting to be read will be returned given one of the following conditions:

In ASCII mode, a blank line will be read as a complete line with length 0, which will be the value returned. sock_bytesready() handles ASCII mode sockets better than sock_dataready(), since it can distinguish between an empty line on the socket and an empty buffer.

For UDP sockets:

Returns the number of bytes in the next datagram to be read. If it is a datagram with no data (an empty datagram), then it will return 0. If there are no datagrams waiting, then it returns -1.

Parameters

s

Pointer to a socket.

Return value

-1: No bytes waiting to be read.
 0: If in ASCII mode and a blank line is waiting to be read;
       for DC 7.05 and later, a UDP datagram with 0 bytes of data is waiting to be read.
>0: The number of bytes waiting to be read.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_established, sockstate


sock_close



void sock_close( void * s );

Description

Attempts to close a socket; no more data may be sent or received through that socket.

In the case of UDP, the socket is closed immediately since UDP is a connectionless protocol. TCP, however, is a connection-oriented protocol so the close must be negotiated with the remote computer. Wait for tcp_tick() to return zero when passed the socket to ensure that a TCP connection is closed.

In emergency cases, it is possible to abort the TCP connection rather than close it. Although not recommended for normal transactions, this service is available and is used by all TCP/IP systems.

Parameters

s

Pointer to a socket.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_abort, sock_tick


sock_dataready



int sock_dataready( void *s );

Description

Returns the number of bytes waiting to be read. If the socket is in ASCII mode, this function returns zero if a newline character has not been read or the buffer is not full. For UDP sockets, the function returns the number of bytes in the next datagram.

This function cannot tell the difference between no bytes to read and either a blank line or a UDP datagram with no data. For this reason, use sock_bytesready() instead.

Parameters

s

Pointer to a socket.

Return value

0: No bytes to read;
       or newline not yet read if the socket is in ASCII mode;
       or (for DC 7.05 and later) if a UDP datagram has 0 bytes of data waiting to be read.
>0: Number of bytes ready to read.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See Also

sock_bytesready


sockerr



char *sockerr( void * s );

Description

Gets the last ASCII error message recorded for the specified socket. Use of this function will introduce a lot of string constants in root memory. For production programs, it is better to use error numbers (without translation to strings).

Parameters

s

Pointer to a socket.

Return value

Pointer to the string that represents the last error message for the socket.

NULL pointer if there have been no errors.

If the symbol SOCKERR_NO_RETURN_NULL is defined, then if no error occurred the string "OK" will be returned instead of a NULL pointer.

The error messages are read-only; do not modify them!

Library

NETERRNO.LIB

See Also

sock_error, sock_perror

Example

char *p;
...
if ( p = sockerr( s ))
printf("Socket closed with error '%s'\n\r", p );


sock_error



int sock_error(void *s, int clear);

Description

Return the most recent error number for the specified socket, which may be a TCP or UDP socket. Up to two error codes may be queued to a socket.

Parameters

s

socket

clear

0: do not clear the returned error condition.

1: clear the returned error from the socket. You can call this function again to get the next older error code (if any).

Return Value

 0: no error.
!0: one of the NETERR_* constants defined in NETERRNO.LIB.

Library

NETERRNO.LIB

See Also

sockerr, sock_perror


sock_established



int sock_established( void *s );

Description

TCP connections require a handshaked open to ensure that both sides recognize a connection. Whether the connection was initiated with tcp_open() or tcp_listen(), sock_established() will continue to return 0 until the connection is established, at which time it will return 1. It is not enough to spin on this after a listen because it is possible for the socket to be opened, written to and closed between two checks. sock_bytesready() can be called with sock_established() to handle this case.

UDP is a connectionless protocol, hence sock_established() always returns 1 for UDP sockets.

Parameters

s

Pointer to a socket.

Return value

0: Not established.
1: Established.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_bytesready, sockstate


sock_fastread



int sock_fastread( tcp_Socket *s, byte *dp, int len );

Description

sock_fastread() attempts to read data from a socket. If possible, the buffer, dp, is filled, otherwise, only the number of bytes read is returned. A return value of -1 indicates a socket error.

This function cannot be used on UDP sockets after sock_recv_init() is called.

Parameters

s

Pointer to a socket.

dp

Buffer to put bytes that are read.

len

Maximum number of bytes to write to the buffer.

Return value

0: Success, number of bytes read.
-1: Error.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_read, sock_fastwrite, sock_write

Example

Note that sock_fastread() and sock_read() do not necessarily return a complete or single line--they return blocks of bytes. In comparison, sock_getc() returns a single byte at a time and thus yields poor performance.


do {
/* this function does not block */
len = sock_fastread( s, buffer, sizeof(buffer)-1 );
if (len>0) {
buffer[ len ] = 0;
printf( "%s", buffer );
}
} while(tcp_tick(s));


sock_fastwrite



int sock_fastwrite( tcp_Socket *s, byte *dp, int len );

Description

Writes up to len bytes from dp on socket s. This function writes as many bytes as possible to the socket and returns that number of bytes.

For UDP, sock_fastwrite() will send one record if
len <= ETH_MTU - 20 - 8

ETH_MTU is the Ethernet Maximum Transmission Unit; 20 is the IP header size and 8 is the UDP header size. By default, this is 572 bytes. If len is greater than this number, then the function does not send the data and returns -1. Otherwise, the UDP datagram would need to be fragmented.

For TCP, the new data is queued for sending and sock_fastwrite() returns the number of bytes that will be sent. The data may be transmitted immediately if enough data is in the buffer, or sufficient time has expired, or the user has explicitly used sock_flushnext() to indicate this data should be flushed immediately. In either case, no guarantee of acceptance at the other end is possible.

Parameters

s

Pointer to a socket.

dp

Buffer to be written.

len

Maximum number of bytes to write to the socket.

Return value

Number of bytes written, or
-1 if there was an error.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_flush



void sock_flush( tcp_Socket *s );

Description

sock_flush() will flush the unwritten portion of the TCP buffer to the network. No guarantee is given that the data was actually delivered. In the case of a UDP socket, no action is taken.

sock_flushnext() is recommended over sock_flush().

Parameters

s

Pointer to a socket.

Return value

None.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_flushnext, sock_fastwrite, sock_write, sockerr


sock_flushnext



void sock_flushnext( tcp_Socket *s );

Description

Writing to TCP sockets does not guarantee that the data are actually transmitted or that the remote computer will pass that data to the other client in a timely fashion. Using a flush function will guarantee that DCRTCP.LIB places the data onto the network. No guarantee is made that the remote client will receive that data.

sock_flushnext() is the most efficient of the flush functions. It causes the next function that sends data to the socket to flush, meaning the data will be transmitted immediately.

Several functions imply a flush and do not require an additional flush: sock_puts(), and sometimes sock_putc() (when passed a \n).

Parameters

s

Pointer to a socket.

Return value

None.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_write, sock_fastread, sock_read, sockerr, sock_flush, sock_flushnext


sock_getc



int sock_getc( tcp_Socket *s );

Description

Gets the next character from the socket. NOTE: This function blocks.

This function cannot be used on UDP sockets after sock_recv_init() is called.

Parameters

s

Pointer to a socket.

Return value

Character read or -1 if error.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Example


do {
if (sock_bytesready( s ) > 0)

      putchar( sock_getc( s ));
} while (tcp_tick(s));


sock_gets



int sock_gets( tcp_Socket *s, char *text, int len );

Description

Reads a string from a socket and replaces the CR or LF with a '\0'. If the string is longer than len, the string is null terminated and the remaining characters in the string are discarded.

To use sock_gets(), you must first set ASCII mode using the function sock_mode()or the macro tcp_set_ascii().

This function cannot be used on UDP sockets after sock_recv_init() is called.

Parameters

s

Pointer to a socket

text

Buffer to put the string.

len

Max length of buffer.

Return value

 0: Either the buffer is empty or the buffer has room and the connection
       can get more data, but no '\r' or '\n' was read.
>0: The length of the string.
-1: Function was called with a UDP socket ( valid for Dynamic C 7.05 and later).

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_puts, sock_putc, sock_getc, sock_read, sock_write

Example


sock_mode( s, TCP_MODE_ASCII );
do {
if (sock_bytesready( s ) > 0) {
sock_gets( s, buffer, sizeof(buffer)-1 );
puts( buffer );
}
} while (tcp_tick( s );


sock_init



int sock_init(void);

Description

This function initializes the packet driver and DCRTCP.LIB using the compiler defaults for configuration. This function must be called before using other DCRTCP.LIB functions.

The return value indicates whether the network is available. If the return code is 1or 3, then the network is not usable. If the return code is 2, then the network is usable because suitable fallbacks were defined; particularly MY_IP_ADDRESS. It is only possible to get return codes 2 or 3 is USE_DHCP is defined. Typically, return codes 2 or 3 mean that there is no DHCP server available within approximately 30 seconds from calling sock_init(). The timeout can be adjusted by setting the global variable _bootptimeout to a suitable value before calling sock_init().

If USE_DHCP and MY_IP_ADDRESS are both defined, then by default the global variable _survivebootp will be set to TRUE. If _survivebootp is set to FALSE before calling sock_init(), then the fallbacks will not be used. That is, return code 2 will never be returned.

If you use ucos2.lib, be sure to call OSInit() before calling sock_init().

Return Value

0: OK.
1: Ethernet packet driver initialization failed.
2: DHCP failed, using fallback definitions.
3: DHCP failed, no fallbacks defined.
Other: reserved.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_mode



word sock_mode( void *s, word mode );

Description

Change some of the socket options. Depending on whether s is a TCP or UDP socket, you may pass OR'd combinations of the following flags in the mode parameter. For a TCP socket, only the TCP_MODE_* flags are relevant. For a UDP socket, only the UDP_MODE_* flags are relevant. Do not use the wrong flags for the given socket type.

Note: it is more convenient, faster, and safer to use the macro equivalent, if it is only desired to change one mode at a time. If you use this function, then you must specify the setting of all relevant flags (TCP or UDP).

The macros do not do socket locking so, strictly speaking, µC/OS users should call this function.

TCP Modes:

TCP_MODE_ASCII | TCP_MODE_BINARY (default)

TCP and UDP sockets are usually in binary mode which means an arbitrary stream of bytes is allowed (TCP is treated as a byte stream and UDP is treated as records filled with bytes.) The default is TCP_MODE_BINARY. By changing the mode to TCP_MODE_ASCII, some of the DCRTCP.LIB functions will see a stream of records terminated with a newline character.

In ASCII mode, sock_bytesready() will return -1 until a newline-terminated string is in the buffer or the buffer is full. sock_puts() will append a newline to any output. sock_gets() (which should only be used in ASCII mode) removes the newline and null terminates the string.

Macros:


tcp_set_binary(s)
tcp_set_ascii(s)

TCP_MODE_NAGLE (default) | TCP_MODE_NONAGLE

The Nagle algorithm may substantially reduce network traffic with little negative effect on a user (In some situations, the Nagle algorithm even improves application performance.) The default is TCP_MODE_NAGLE. This mode only affects TCP connections.

Macros:


tcp_set_nagle(s)
tcp_set_nonagle(s)


UDP Modes:

UDP_MODE_CHK | UDP_MODE_NOCHK

Checksums are required for TCP, but not for UDP. The default is UDP_MODE_CHK. If you are providing a checksum at a higher level, the low-level checksum may be redundant. The checksum for UDP can be disabled by selecting the UDP_MODE_NOCHK flag. Note that you do not control whether the remote computer will send checksums. If that computer does checksum its outbound data, DCRTCP.LIB will check the received packet's checksum.

Macros:


udp_set_chk(s)
udp_set_nochk(s)

UDP_MODE_NOICMP (default) | UDP_MODE_ICMP

Marks this socket for receipt of ICMP error messages. The messages are queued like normal received datagrams, and read using udp_recvfrom(), which returns -3 when ICMP messages are returned instead of normal datagrams. Only ICMP messages which are relevant to the current binding of the socket are queued.

Macros:


udp_set_noicmp(s)
udp_set_icmp(s)

UDP_MODE_NODICMP (default) | UDP_MODE_DICMP

Marks this socket as the default receiver of ICMP messages which cannot be assigned to a particular UDP socket. This would be used for UDP sockets that are used with many different sendto addresses, since the ICMP message may refer to a message sent some time ago (with different destination address than the most recent). Only one UDP socket should be set with this mode.

Macros:


udp_set_nodicmp(s)
udp_set_dicmp(s)

Parameters

s

Pointer to a socket.

mode

New mode for specified socket.

Return Value

Resulting mode flags

See Also

inet_addr

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_perror



void sock_perror(void *s, const char * prefix);

Description

Prints out the most recent error messages for a socket, and clear the errors. This calls sockerr() and printf(), so it should only be called for debugging a new application. The output is in the format:


[TCP|UDP] socket (ipaddr:port -> ipaddr:port) msg1; msg2 

where msg1 and, possibly, msg2 are the most recent error messages. The initial string is "TCP" or "UDP" for open sockets, or may be "Closed" if the socket is currently closed (either TCP or UDP). Up to two error codes may be queued to a socket.

If there are no errors, nothing is printed.

Parameters

s

Pointer to TCP or UDP socket.

prefix

Pointer to text to add to generated messages, or NULL.

Library

NETERRNO.LIB

See Also

sock_error, sockerr


sock_preread



int sock_preread( tcp_Socket *s, byte *dp, int len );

Description

This function reads up to len bytes from the socket into the buffer dp. The bytes are not removed from the socket's buffer.

Parameters

s

Pointer to a socket structure.

dp

Buffer to preread into.

len

Maximum number of bytes to preread.

Return value

 0: No data waiting.
-1: Error.
>0: Number of preread bytes.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_fastread, sock_fastwrite, sock_read, sock_write


sock_putc



byte sock_putc( tcp_Socket *s, byte c );

Description

A single character is placed on the output buffer. In the case of `\n', the buffer is flushed as described under sock_flushnext. No other ASCII character expansion is performed.

Note that sock_putc uses sock_write, and thus may block if the output buffer is full. See sock_write for more details.

Parameters

s

Pointer to a socket.

c

Character to send.

Return value

The character c.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_read, sock_write, sock_fastread, sock_fastwrite, sock_mode


sock_puts



int sock_puts( tcp_Socket *s, byte *dp );

Description

A string is placed on the output buffer and flushed as described under sock_flushnext(). If the socket is in ASCII mode, CR and LF are appended to the string. No other ASCII character expansion is performed. In binary mode, the string is sent as is.

Note that sock_puts() uses sock_write(), and thus may block if the output buffer is full. See sock_write() for more details.

Parameters

s

Pointer to a socket.

dp

Buffer to read the string from.

Return value

0: Length of string in dp.
-1: Function was called with a UDP socket (valid for Dynamic C 7.05 and later).

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_gets, sock_putc, sock_getc, sock_read, sock_write


sock_rbleft



int sock_rbleft( void *s );

Description

Determines the number of bytes available in the receive buffer.

Parameters

s

Pointer to a socket.

Return value

Number of bytes available in the receive buffer.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbsize, sock_rbused, sock_tbsize, sock_tbused, sock_tbleft


sock_rbsize



int sock_rbsize( void *s );

Description

Determines the size of the receive buffer for the specified socket.

Parameters

s

Pointer to a socket.

Return value

The size of the receive buffer.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbleft, sock_rbused, sock_tbsize, sock_tbused, sock_tbleft


sock_rbused



int sock_rbused( void *s );

Description

Returns the number of bytes in use in the receive buffer for the specified socket.

Parameters

s

Pointer to a socket.

Return value

Number of bytes in use.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbleft, sock_tbsize, sock_tbused, sock_tbleft


sock_read



int sock_read( tcp_Socket *s, byte *dp, int len );

Description

sock_read() will busywait until len bytes are read or a socket error exists. If sock_yield() has been called, the user-defined function that is passed to it will be called in a tight loop while sock_read() is busywaiting.

This function cannot be used on UDP sockets after sock_recv_init() is called.

Parameters

s

Pointer to a socket.

dp

Buffer to store bytes that are read.

len

Maximum number of bytes to write into the buffer.

Return value

Number of bytes read: Success.
-1: Error.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_fastread, sock_fastwrite, sock_write, sockerr

Example

Note that sock_fastread() and sock_read() do not necessarily return a complete or single line--they return blocks of bytes. In comparison, sock_getc() returns a single byte at a time and thus yields poor performance.


do {
len = sock_bytesready( s );
if (len > 0) {
if (len > sizeof( buffer) - 1)
{                                 // If too many bytes, read
len = sizeof( buffer ) - 1;    // some now, read the rest
}                                 // next time around.
sock_read( s, buffer, len );
buffer[ len ] = 0;
printf( "%s", buffer );
}
} while ( tcp_tick( s ));


sock_recv



int sock_recv( sock_type *s, char *buffer, int len );

Description

After a UDP socket is initialized with udp_open() and sock_recv_init(), sock_recv() scans the buffers for any datagram received by that socket. This function is not available starting with Dynamic C 7.05 (see Section 2.3).

Parameters

s

Pointer to a UDP socket.

buffer

Buffer to put datagram.

maxlength

Length of buffer.

Return value

>0: Length of datagram.
 0: No datagram found.
-1: Receive buffer not initialized with sock_recv_init().

Library

DCRTCP.LIB

See also

sock_recv_from, sock_recv_init

Example using sock_recv()


#define MY_IP_ADDRESS "10.10.6.100"
#define MY_NETMASK "255.255.255.0"
#memmap xmem

#use "dcrtcp.lib"

#define SAMPLE 401

udp_Socket data;
char bigbuf[ 8192 ];

main() {
word templen;
char spare[ 1500 ];

sock_init();
if ( !udp_open( &data, SAMPLE, 0xffffffff, SAMPLE, NULL) ) {
puts("Could not open broadcast socket");
exit( 3 );
}

/* set large buffer mode */
if ( sock_recv_init( &data, bigbuf, sizeof( bigbuf ))) {
puts("Could not enable large buffers");
exit( 3 );
}

sock_mode( &data, UDP_MODE_NOCHK ); /* turn off checksums */

while (1) {
tcp_tick( NULL );

if ( templen = sock_recv( &data, spare, sizeof( spare ))) {
/* something received */
printf("Got %u byte packet\n", templen );
}
}
}


sock_recv_from



int sock_recv_from( sock_type *s, long *hisip, word *hisport, char *buffer, int len);

Description

After a UDP socket is initialized with udp_open() and sock_recv_init(), sock_recv_from () scans the buffers for any datagram received by that socket and identifies the remote host's address. This function is not available starting with Dynamic C 7.05 (see Section 2.3).

Parameters

s

Pointer to UDP socket.

hisip

IP of remote host, according to UDP header.

hisport

Port of remote host.

buffer

Buffer to put datagram in.

len

Length of buffer.

Return value

>0: Length of datagram received;
 0: No datagram;
-1: Receive buffer was not initialized with sock_recv_init().

Library

DCRTCP.LIB

See also

sock_recv, sock_recv_init


sock_recv_init



int sock_recv_init( sock_type *s, void *space, word len);

Description

This function is not available starting with Dynamic C 7.05 (see Section 2.3).

The basic socket reading functions (sock_read(), sock_fastread(), etc.) are not adequate for all your UDP needs. The most basic limitation is their inability to treat UDP as a record service.

A record service must receive distinct datagrams and pass them to the user program as such. You must know the length of the received datagram and the sender (if you opened in broadcast mode). You may also receive the datagrams very quickly, so you must have a mechanism to buffer them.

Once a socket is opened with udp_open(), you can use sock_recv_init() to initialize that socket for sock_recv() and sock_recv_from(). Note that sock_recv() and related functions are incompatible with sock_read(), sock_fastread(), sock_gets() and sock_getc(). Once you have used sock_recv_init(), you can no longer use the older-style calls.

sock_recv_init() installs a large buffer area which gets segmented into smaller buffers. Whenever a UDP datagram arrives, DCRTCP.LIB stuffs that datagram into one of these new buffers. The new functions scan those buffers. You must select the size of the buffer you submit to sock_recv_init(); make it as large as possible, say 4K, 8K or 16K.

For a sample program, see Example using sock_recv() listed under sock_recv().

Parameters

s

Pointer to a UDP socket.

space

Buffer of temporary storage space to store newly received packets.

len

Size of the buffer.

Return value

0

Library

DCRTCP.LIB

See also

sock_recv_from, sock_recv


sock_resolved



int sock_resolved(void * s)

Description

Check whether the socket has a valid destination hardware address. This is typically used for UDP sockets, but may also be used for TCP sockets. If this function returns zero (FALSE), then any datagrams you send using udp_send() or udp_sendto() may not be transmitted because the destination hardware address is not known.

If the current destination IP address of the socket is zero (i.e. the socket is passively opened), this function returns zero, since datagrams cannot be transmitted from a passively opened socket.

If udp_bypass_arp() is in effect, the return value from this function is unaffected, however datagrams will still be sent to the specified hardware address (since the normal resolve process is bypassed).

Note that a hardware address may become invalid after being valid, since the underlying ARP table may need to purge the entry. This would be rare, but if any UDP application needs to ensure that all packets are actually transmitted, which is a questionable goal since UDP is unreliable, then this function should be consulted before each send. If this function returns 0, then the UDP socket should be re-opened.

The hardware address may also be invalidated if udp_sendto() is called with a different destination IP address, that has not been determined based on an incoming datagram.

This function is not required for TCP sockets, since the TCP library handles these details internally.

Parameter

s

Pointer to open TCP or UDP socket

Return Value:

 0: Destination hardware address not valid
!0: Destination hardware address resolved OK.

Library

NET.LIB

See Also

udp_extopen, arpresolve_start, arpresolve_check, udp_waitopen, udp_sendto, udp_bypass_arp


sock_set_tos



void sock_set_tos(void* s, byte tos);

Description

Set the IP "Type Of Service" field in outgoing packets for this socket. The given TOS will be in effect until the socket is closed. When a socket is opened (or re-opened), the TOS will be set to the default (TCP_TOS or UDP_TOS as appropriate). If not overridden, the defaults are zero (IPTOS_DEFAULT) in both cases.

Parameters

s

Pointer to open TCP or UDP socket.

tos

Type Of Service. This should be one of the following values:

· IPTOS_DEFAULT - Default service
· IPTOS_CHEAP - Minimize monetary cost
· IPTOS_RELIABLE - Maximize reliability
· IPTOS_CAPACIOUS - Maximize throughput
· IPTOS_FAST - Minimize delay
· IPTOS_SECURE - Maximize security.

Other value may be used (since TOS is just a number between 0 and 255), but this should only be done for experimental purposes.

Library

NET.LIB

See Also

sock_set_ttl


sock_set_ttl



void sock_set_ttl(void* s, byte ttl);

Description

Set the IP "Time To Live" field in outgoing packets for this socket. The given TTL will be in effect until the socket is closed. When a socket is opened (or re-opened), the TTL will be set to the default (TCP_TTL or UDP_TTL as appropriate). If not overridden, the defaults are 64 in both cases.

Parameters

s

Pointer to open TCP or UDP socket.

ttl

Time To Live. This is a value between 1 and 255. A value of zero is also accepted, but will have undesirable consequences.

Library

NET.LIB

See Also

sock_set_tos


sockstate



char *sockstate( void * s );

Description

Returns a string that gives the current state for a socket.

Parameters

s

Pointer to a socket.

Return value

An ASCII message which represents the current state of the socket. These strings should not be modified.

"Listen" indicates a passively opened socket that is waiting for a connection.

"SynSent" and "SynRcvd" are connection phase intermediate states.

"Established" states that the connection is complete.

"EstClosing" "FinWait1" "FinWait2" "CloseWait" "Closing" "LastAck" "TimeWait" and "CloseMSL" are connection termination intermediate states.

"Closed" indicates that the connection is completely closed.

"UDP Socket" is always returned for UDP sockets because they are stateless.

"Not an active socket" is a default value used when the socket is not recognized as UDP or TCP.

"BAD" more than one bit set.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_established, sock_dataready

Example


char *p;
...
#ifdef DEBUG
if ( p = sockstate( s ))
printf("Socket state is '%s'\n\r", p );
#endif DEBUG


sock_tbleft



int sock_tbleft( void *s );

Description

Gets the number of bytes left in the transmit buffer. If you do not wish to block, you may first query how much space is available for writing by calling this function before generating data that must be transmitted. This removes the need for your application to also buffer data.

Parameters

s

Pointer to a socket.

Return value

Number of bytes left in the transmit buffer.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbsize, sock_rbused, sock_rbleft, sock_tbsize, sock_tbused


if ( sock_tbleft( s ) > 10 ) {
/* we can send up to 10 bytes without blocking or overflowing */
....
}


sock_tbsize



int sock_tbsize( void *s );

Description

Determines the size of the transmit buffer for the specified socket.

Parameters

s

Pointer to a socket.

Return value

The size of the transmit buffer.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbsize, sock_rbused, sock_rbleft, sock_tbleft, sock_tbused


sock_tbused



int sock_tbused( void *s );

Description

Gets the number of bytes in use in the transmit buffer for the specified socket.

Parameters

s

Pointer to a socket.

Return value

Number of bytes in use.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_rbsize, sock_rbused, sock_rbleft, sock_tbsize, sock_tbleft


sock_tick



void sock_tick( void * s, int * optional_status_ptr );

Description

This macro calls tcp_tick() to quickly check incoming and outgoing data and to manage all the open sockets. If our particular socket, s, is either closed or made inoperative due to an error condition, sock_tick() sets the value of *optional_status_ptr (if the pointer is not NULL) to 1, then jumps to a local, user-supplied label, sock_err. If the socket connection is fine and the pointer is not NULL *optional_status_ptr is set to 0.

Parameters

s

Pointer to a socket.

optional_status_ptr

Pointer to status word.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_wait_closed



void sock_wait_closed(void * s, int seconds, int (*fptr)(), int* status);

Description

This macro waits until a TCP connection is fully closed. Returns immediately for UDP sockets. On an error, the macro jumps to a local, user-supplied sock_err label. If fptr returns non-zero the macro returns with the status word set to the value of fptr`s return value.

This macro has been deprecated in Dynamic C version 7.20.

Parameters

s

Pointer to a socket.

seconds

Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main().

fptr

Function to call repeatedly while waiting. This is a user-supplied function.

status

Pointer to a status word.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_wait_established



void sock_wait_established(void* s, int seconds, int (*fptr)(), int* status);

Description

This macro waits until a connection is established for the specified TCP socket, or aborts if a time-out occurs. It returns immediately for UDP sockets. On an error, the macro jumps to the local, user-supplied sock_err label. If fptr returns non-zero, the macro returns.

This macro has been deprecated in Dynamic C version 7.20.

Parameters

s

Pointer to a socket.

seconds

Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main().

fptr

Function to call repeatedly while waiting. This is a user-supplied function.

status

Pointer to a status word.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_wait_input



void sock_wait_input(void* s, int seconds, int (*fptr)(), int* status);

Description

Waits until input exists for functions such as sock_read() and sock_gets(). As described under sock_mode(), if in ASCII mode, sock_wait_input only returns when a complete string exists or the buffer is full. It returns immediately for UDP sockets.

On an error, the macro jumps to a local, user-supplied sock_err label. If fptr returns non-zero, the macro returns.

This macro has been deprecated in Dynamic C version 7.20.

Parameters

s

Pointer to a socket.

seconds

Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main().

fptr

Function to call repeatedly while waiting.

status

A pointer to the status word. If this parameter is NULL, no status number will be available, but the macro will otherwise function normally. Typically the pointer will point to a local signed integer that is used only for status. status may be tested to determine how the socket was ended. A value of 1 means a proper close while a -1 value indicates a reset or abort.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


sock_write



int sock_write( tcp_Socket *s, byte *dp, int len );

Description

Writes up to len bytes from dp on socket s. This function busywaits until either the buffer is completely written or a socket error occurs. If sock_yield() has been called, the user-defined function that is passed to it will be called in a tight loop while sock_write() is busywaiting.

For UDP, sock_write() will send one (or more) records. For TCP, the new data may be transmitted if enough data is in the buffer or sufficient time has expired or the user has explicitly used sock_flushnext() to indicate this data should be flushed immediately. In either case, there is no guarantee of acceptance at the other end.

Parameters

s

Pointer to a socket

dp

Pointer to a buffer.

len

Maximum number of bytes to write to the buffer.

Return value

Number of bytes written or -1 on an error.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

sock_read, sock_fastwrite, sock_fastread, sockerr, sock_flush, sock_flushnext


sock_yield



int sock_yield( tcp_Socket *s, void (*fn)());

Description

This function, if called prior to one of the blocking functions, will cause fn, the user-defined function that is passed in as the second parameter, to be called repeatedly while the blocking function is in a busywait state.

Parameters

s

Pointer to a TCP socket.

fn

User-defined function.

Return value

0

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


tcp_clearreserve



void tcp_clearreserve( word port );

Description

This function causes the DCRTCP.LIB stack to handle a socket connection to the specified port normally. This undoes the action taken by tcp_reserveport().

Parameters

port

Port to use.

Return value

None.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

tcp_reserveport


tcp_config



void tcp_config(char *name, char *value);

Description

Sets TCP/IP stack parameters at runtime. It should not be called with open sockets.

Note that there are specific (and safer) functions for modifying some of the common parameters.

This function is deprecated. It is highly recommended that you do NOT use it, since it uses strings, hence taking up lots of root data storage.

Parameters

name

Setting to be changed. The possible parameters are:

value

The value to assign to name.

Return value

None.

Library

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See Also

tcp_open, sock_close, sock_abort, sethostid, setdomainname, sethostname


tcp_extlisten



int tcp_extlisten( tcp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, word reserved, long buffer, int buflen );

Description

This function tells the TCP/IP engine that an incoming session for a particular port will be accepted. The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool. tcp_extlisten() is an extended version of tcp_listen().

Parameters

s

Pointer to the socket's data structure.

iface

Local interface on which to open the socket (not yet implemented, use IF_DEFAULT for now).

lport

Port to listen on.

remip

IP address to accept connections from or 0 for all.

port

Port to accept connections from or 0 for all.

datahandler

Function to call when data is received, NULL for placing data in the socket's receive buffer. Some details for implementation of this service have not been finalized, and it is recommended the user insert a value of NULL for the present time.

reserved

Set to 0 for now. This parameter is for compatibility and possible future use.

buffer

Address of user-supplied socket buffer in xmem. This is the return value of xalloc(). If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_TCP_SOCKET_BUFFERS.

buflen

Length of user-supplied socket buffer.

Return value

0: Failure.
1: Success.

Library

TCP.LIB

See also

tcp_listen


tcp_extopen



int tcp_extopen(tcp_Socket* s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen);

Description

Actively creates a session with another machine. The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool. tcp_extopen() is an extended version of tcp_open().

s

Pointer to socket's data structure.

iface

Local interface on which to open the socket (not yet implemented, use IF_DEFAULT for now).

lport

Our port, zero for the next one available in the range 1025-65536.

remip

IP address to connect to.

port

Port to connect to.

datahandler

Function to call when data is received, NULL for placing data in the socket's receive buffer. Some details for implementation of this service have not been finalized, and it is recommended the user insert a value of NULL for the present time.

buffer

Address of user-supplied socket buffer in xmem. This is the return value of xalloc(). If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_TCP_SOCKET_BUFFERS.

buflen

Length of user-supplied socket buffer.

Return value

 0 if open was not able resolve the remote computer's hardware address,
!0 otherwise.

Library

TCP.LIB

See also

tcp_open


tcp_keepalive



int tcp_keepalive(tcp_Socket *s, long timeout);

Description

Enable or disable TCP keepalives on a specified socket. The socket must already be open. Keepalives will then be sent after timeout seconds of inactivity. It is highly recommended to keep timeout as long as possible, to reduce the load on the network. Ideally, it should be no shorter than 2 hours. After the timeout is sent, and KEEPALIVE_WAITTIME seconds pass, another keepalive will be sent, in case the first was lost. This will be retried KEEPALIVE_NUMRETRYS times. Both of these macros can be defined at the top of your program, overriding the defaults of 60 seconds, and 4 retries.

Using keepalives is not a recommended procedure. Ideally, the application using the socket should send its own keepalives. tcp_keepalive() is provided because telnet and a few other network protocols do not have a method of sending keepalives at the application level.

Parameters

s

Pointer to a socket.

timeout

Period of inactivity, in seconds, before sending a keepalive or 0 to turn off keepalives.

Return value

0: Success.
1: Failure.

Library

TCP.LIB

See also

sock_fastread, sock_fastwrite, sock_write, sockerr


tcp_listen



int tcp_listen( tcp_Socket *s, word lport, longword remip, word port, int (*signal_handler), word reserved );

Description

This function tells DCRTCP.LIB that an incoming session for a particular port will be accepted. After a call to tcp_listen(), the function sock_established() (or the macro sock_wait_established) must be called to poll the connection until a session is fully established.

It is possible for a connection to be opened, written to and closed between two calls to the function sock_established(). To handle this case, call sock_bytesready() to determine if there is data to be read from the buffer.

Multiple calls to tcp_listen() to the same local port (lport) are acceptable and constitute the DCRTCP.LIB mechanism for supporting multiple incoming connections to the same local port. Each time another host attempts to open a session on that particular port, another one of the listens will be consumed until such time as all listens have become established sessions and subsequent remote host attempts will receive a reset.

Parameters

s

Pointer to a socket.

lport

Port to listen on (the local port number).

remip

IP address of the remote host to accept connections from or 0 for all.

port

Port to accept connections from or 0 for all.

signal_handler

This function is called if the connection is either closed or reset. The parameter for signal_handler is the pointer to a function which will be called when the socket is either closed or reset. Some details for implementation of this service have not been finalized, and it is recommended the user insert a value of NULL for the present time.

reserved

Set to 0 for now. This parameter is for compatibility and possible future use.

Return value

0: Failure.
1: Success.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

tcp_open

Example using tcp_listen()


#define MY_IP_ADDRESS "10.10.6.100"
#define MY_NETMASK "255.255.255.0"
#memmap xmem
#use "dcrtcp.lib"

#define TELNET_PORT 23

static tcp_Socket *s;
char *userid;

telnets(int port) {
tcp_Socket telnetsock;
char buffer[ 512 ];
int status;
s = &telnetsock;
tcp_listen( s, port, 0L, 0, NULL, 0);

while (!sock_established(s) && sock_bytesready(s)==-1){
tcp_tick(NULL);
}
puts("Receiving incoming connection");
sock_mode( s, TCP_MODE_ASCII );
sock_puts( s, "Welcome to a sample telnet server.");
sock_puts( s, "Each line you type will be printed on this"\
"screen once you hit return.");
/* other guy closes connection except if we timeout ... */
do {
if (sock_bytesready(s) >= 0) {
sock_gets(s, buffer, sizeof(buffer)-1);
puts ( buffer);
}

    } while (tcp_tick(s));
}
main() {
sock_init();
telnets( TELNET_PORT);
exit( 0 );
}


tcp_open



int tcp_open( tcp_Socket *s, word lport, longword remip, word port, int (*signal_handler)());

Description

This function actively creates a session with another machine. After a call to tcp_open(), the function sock_established() (or the macro sock_wait_established) must be called to poll the connection until a session is fully established.

It is possible for a connection to be opened, written to and closed between two calls to the function sock_established(). To handle this case, call sock_bytesready() to determine if there is data to be read from the buffer.

Parameters

s

Pointer to a socket structure.

lport

Our local port. Use zero for the next available port in the range 1025-65536. A few applications will require you to use a particular local port number, but most network applications let you use almost any port with a certain set of restrictions. For example, FINGER or TELNET clients can use any local port value, so pass the value of zero for lport and let DCRTCP.LIB pick one for you.

remip

IP address to connect to.

port

Port to connect to.

signal_handler

This function is called if the connection is either closed or reset. The parameter for signal_handler is the pointer to a function which will be called when the socket is either closed or reset. Some details for implementation of this service have not been finalized, and it is recommended the user insert a value of NULL for the present time.

Return value

 0: Unable to resolve the remote computer's hardware address;
!0 otherwise.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

tcp_listen

Example Using tcp_open()


#define MY_IP_ADDRESS "10.10.6.100"
#define MY_NETMASK "255.255.255.0"
#memmap xmem

#use "dcrtcp.lib"

#define ADDRESS "10.10.6.19"
#define PORT "200"

main() {
word status;
word port;
longword host;
tcp_Socket tsock;

sock_init();

if (!(host = resolve(ADDRESS))) {
puts("Could not resolve host");
exit( 3 );
}
port = atoi( PORT );
printf("Attempting to open '%s' on port %u\n\r", ADDRESS, port );
if ( !tcp_open( &tsock, 0, host, port , NULL )) {
puts("Unable to open TCP session");
exit( 3 );
}

printf("Waiting a maximum of %u seconds for connection"\
" to be established\n\r", sock_delay );

while (!sock_established(&tsock) && sock_bytesready(&tsock)==-1){
tcp_tick(NULL);
}
puts("Socket is established");
sock_close( &tsock );
exit( 0 );
}


tcp_reserveport



void tcp_reserveport( word port );

Description

This function allows a connection to be established even if there is not yet a socket available. This is done by setting a parameter in the TCP header during the connection setup phase that indicates 0 bytes of data can be received at the present time. The requesting end of the connection will wait until the TCP header parameter indicates that data will be accepted.

The 2MSL waiting period for closing a socket is avoided by using this function.

The penalty of slower connection times on a controller that is processing a large number of connections is offset by allowing the program to have less sockets and consequently less RAM usage.

Parameters

port

Port to use.

Return value

None.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

tcp_clearreserve


tcp_tick



int tcp_tick( void *s );

Description

This function is a single kernel routine designed to quickly process packets and return as soon as possible. tcp_tick() performs processing on all sockets upon each invocation: checking for new packets, processing those packets, and performing retransmissions on lost data. On most other computer systems and other kernels, performing these required operations in the background is often done by a task switch. DCRTCP.LIB does not use a tasker for its basic operation, although it can adopt one for the user-level services.

Although you may ignore the returned value of tcp_tick(), it is the easiest method to determine the status of the given socket.

Parameters

s

Pointer to a socket. If NULL, the returned value is always 0.

Return value

 0: Connection reset or closed by other host or NULL was passed in.
!0: Connection is fine.

Library

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

tcp_open, sock_close, sock_abort, sock_tick


udp_bypass_arp



void udp_bypass_arp(udp_Socket *s, eth_address * eth);

Description

Override the normal Address Resolution Protocol for this UDP socket. This is sometimes necessary for special purposes such as if the ethernet address is to remain fixed, or if the ethernet address is not obtainable using ARP. The great majority of applications should not use this function.

If ARP bypass is in effect for a UDP socket, then udp_sendto() will never return the -2 return code.

Parameters

s

UDP socket

eth

Pointer to override address. If NULL, then resume normal operation i.e. use ARP to resolve ethernet addresses. Note that the specified ethernet address must be in static storage, since only the pointer is stored.

Library

UDP.LIB

See Also

udp_sendto, udp_waitsend, sock_resolved


udp_close



void udp_close(udp_Socket *ds);

Description

This function closes a UDP connection.

Parameters

ds

Pointer to socket's data structure.

Library

UDP.LIB


udp_extopen



int udp_extopen( udp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen );

Description

This function is an extended version of udp_open(). It opens a socket on a given network interface (iface) on a given local port (lport). The iface parameter is not currently supported and should be IF_DEFAULT. The remote end of the connection is specified by remip and port. The following table explains the possible combinations and what they mean.

REMIP Effect of REMIP value
0 The connection completes when the first datagram is received, supplying both the remote IP address and the remote port number. Only datagrams received from that IP/port address will be accepted.
-1 All remote hosts can send datagrams to the socket. All outgoing datagrams will be sent to the broadcast address on the specified port.
>0 If the remote IP address is a valid IP address and the remote port is 0, the connection will complete when the first datagram is received, supplying the remote port number. If the remote IP address and the remote port are both specified when the function is called, the connection is complete at that point.

The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool.

If remip is non-zero, then the process of resolving the correct destination hardware address is started. Datagrams cannot be sent until sock_resolved() returns TRUE. If you attempt to send datagrams before this, then the datagrams may not get sent. The exception to this is if remip is -1 (broadcast) in which case datagrams may be sent immediately after calling this function.



Parameters

s

Pointer to socket's data structure.

iface

Local interface on which to open the socket (not yet implemented--use IF_DEFAULT for now).

lport

Local port.

remip

Acceptable remote IP, or 0 for all.

port

Acceptable remote port, or 0 for all.

datahandler

Function to call when data is received, NULL for placing data in the socket's receive buffer.

buffer

Address of user-supplied socket buffer in xmem. If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_UDP_SOCKET_BUFFERS.

buflen

Length of user-supplied socket buffer.

Return value:

!0: Success.
0: Failure; error opening socket, e.g., a buffer could not be allocated.

Library

UDP.LIB

See Also

udp_open, sock_resolved


udp_open



int udp_open( udp_Socket *s, word lport, longword remip, word port, dataHandler_t datahandler);

Description

This function opens a UDP socket on the given local port (lport). The remote end of the connection is specified by remip and port. The following table explains the possible combinations and what they mean.

Table 1.
REMIP Effect of REMIP value
0 The connection completes when the first datagram is received, supplying both the remote IP address and the remote port number. Only datagrams received from that IP/port address will be accepted.
-1 All remote hosts can send datagrams to the socket. All outgoing datagrams will be sent to the broadcast address on the specified port.
>0 If the remote IP address is a valid IP address and the remote port is 0, the connection will complete when the first datagram is received, supplying the remote port number. If the remote IP address and the remote port are both specified when the function is called, the connection is complete at that point.

If the remote host is set to a particular address, either host may initiate traffic. Multiple calls to udp_open() with remip set to zero is a useful way of accepting multiple incoming sessions.

Although multiple calls to udp_open() may normally be made with the same lport number, only one udp_open() should be made on a particular lport if the remip is set to -1. Essentially, the broadcast and nonbroadcast protocols cannot co-exist.

Be sure that you have allocated enough UDP socket buffers with MAX_UDP_SOCKET_BUFFERS. Note that this macro defaults to 0, so any usage of udp_open() requires a definition of MAX_UDP_SOCKET_BUFFERS in your program.

Parameters

s

Pointer to a UDP socket.

lport

Local port

remip

Acceptable remote IP, 0 to connect on first datagram, or -1 for broadcast.

port

Acceptable remote port, or 0 to connect on first datagram.

datahandler

Function to call when data is received. NULL for placing data in the socket's receive buffer.



Return value

 0: Failure (e.g., a buffer could not be allocated).
!0: Success.

Library

UDP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

See also

udp_extopen


udp_peek



int udp_peek(udp_Socket* s, _udp_datagram_info * udi);

Description

Look into the UDP socket receive buffer to see if there is a datagram ready to be read using udp_recvfrom(). This function does not remove the datagram from the buffer, but it allows the application to determine the full details about the next datagram, including whether the datagram was broadcast.

The returned data is put in *udi. udi must point to a valid data structure, or be NULL. The data structure is:


typedef struct {
longword remip; // Remote host IP address
word remport; // Remote host port number
int len; // Length of datagram
byte flags; // Flags
byte iface; // Interface number
} _udp_datagram_info;

The flags field may have one of the following values:


UDI_ICMP_ERROR     This is an ICMP error entry.
UDI_TOS_MASK       Type-of-service bit mask.
UDI_BROADCAST_LL   Received on broadcast link-layer address.
UDI_BROADCAST_IP   Received on broadcast network (IP) address.

Parameters

s

UDP socket to check

udi

Where to store the returned information.

Return Value

 1: A normal datagram is in the receive buffer.
 0: No datagram waiting.

-3: An ICMP error message is in the receive buffer - this will only be returned if udi parameter is not NULL.

Library

UDP.LIB

See Also

udp_recvfrom


udp_recv



int udp_recv(udp_Socket* s, char* buffer, int len)

Description

Receives a single UDP datagram on a UDP socket. If the buffer is not large enough for the datagram, the datagram is truncated, and the remainder discarded.

Parameters

s

Pointer to socket's data structure.

buffer

Buffer where the UDP datagram will be stored.

len

Maximum length of the buffer.

Return value

 0: Number of bytes received.
 -1: No datagram waiting.
<-1: Error.

Library

UDP.LIB

See also

udp_recvfrom, udp_send, udp_sendto, udp_open


udp_recvfrom



int udp_recvfrom(udp_Socket* s, char* buffer, int len, longword* remip, word* remport);

Description

Receive a single UDP datagram on a UDP socket. remip and remport should be pointers to the locations where the remote IP address and remote port from which the datagram originated are placed. If the buffer is not large enough for the datagram, then the datagram will be truncated, with the remainder being discarded.

If and only if the UDP_MODE_ICMP or UDP_MODE_DICMP modes are set for this socket, then a return code of -3 indicates that an ICMP error message is being returned in the buffer instead of a normal datagram. In this case, buffer will contain fixed data in the form of a structure of type _udp_icmp_message. The definition of this structure is:


typedef struct {
word myport;         // Originating port on this host
byte icmp_type;      // One of the ICMPTYPE_* values
byte icmp_code;      // The corresponding ICMP code
} _udp_icmp_message;

Please see sock_mode for more information about the modes UDP_MODE_ICMP and UDP_MODE_DICMP.

Parameters

s

Pointer to socket's data structure.

buffer

Buffer where the UDP datagram will be stored.

len

Maximum length of the buffer.

remip

IP address of the remote host of the received datagram.

remport

Port number of the remote host of the received datagram.

Return value

0: Number of bytes received.
-1: No datagram waiting.
-2: Error - not a UDP socket.
-3: The returned buffer contains an ICMP error which was queued previously.

Library

UDP.LIB

See also

udp_recv, udp_send, udp_sendto, udp_open, udp_peek


udp_send



int udp_send(udp_Socket* s, char* buffer, int len);

Description

Sends a single UDP datagram on a UDP socket. It will not work for a socket for which the remip parameter to udp_open() was 0, unless a datagram has first been received on the socket. If the remip parameter to udp_open() was -1, the datagram will be send to the broadcast address.

Parameters

s

Pointer to socket's data structure.

buffer

Buffer that contains the UDP datagram

len

Length of the UDP datagram.

Return value

0: Number of bytes sent.
-1: Failure.

Library

UDP.LIB

See also

udp_sendto, udp_recv, udp_recvfrom, udp_open


udp_sendto



int udp_sendto(udp_Socket* s, char* buffer, int len, longword remip, word remport);

Description

Sends a single UDP datagram on a UDP socket. It will send the datagram to the IP address and port specified by remip and remport. Note that this function can be used on a socket that has been "connected" to a different remote host and port.

Parameters

s

Pointer to socket's data structure.

buffer

Buffer that contains the UDP datagram.

len

Length of the UDP datagram.

remip

IP address of the remote host.

remport

Port number of the remote host.

Return value

0: Success, number of bytes sent.
-1: Failure.
-2: Failed because hardware address not resolved.

Library

UDP.LIB

See also

udp_send, udp_recv, udp_recvfrom, udp_open


udp_waitopen



int udp_waitopen( udp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen, longword millisecs );

Description

This function is identical to udp_extopen(), except that it waits a specified amount of time for the hardware address of the destination to be resolved.

While waiting, this function calls tcp_tick().

Parameters

s

Pointer to socket.

iface

Local interface on which to open the socket (not yet implemented so use IF_DEFAULT for now).

lport

Local port.

remip

Acceptable remote ip, or 0 for all.

port

Acceptable remote port, or 0 for all.

datahandler

Function to call when data is received, NULL for placing data in the sockets receive buffer.

buffer

Address of user-supplied socket buffer in xmem, 0 to use a buffer from the socket buffer pool.

buflen

Length of user-supplied socket buffer.

millisecs

Maximum milliseconds to wait for the hardware address to be resolved.

Return Value

>0: Successfully opened socket.
 0: Timed out without resolving address.
-1: Error opening socket (e.g., buffer could not be allocated).

Library

UDP.LIB

See Also

udp_extopen, sock_resolved


udp_waitsend



int udp_waitsend(udp_Socket* s, char* buffer, int len, longword remip, word remport, word millisecs);

Description

This is identical to udp_sendto(), except that it will block for up to the specified amount of time waiting for the hardware address to be resolved. Normally, you should not have to specify more than 100ms for the time out. If it takes longer than this, the destination is probably unavailable.

Parameters

s

UDP socket on which to send the datagram.

buffer

Buffer that contains the UDP datagram.

len

Length of the UDP datagram.

remip

IP address of the remote host.

remport

Port number of the remote host.

millisecs

Number of milliseconds to wait for hardware address resolution. Reasonable values are between 50 and 750 milliseconds.

Return Value

0: Number of bytes sent.
-1: Failure (invalid UDP socket etc.).
-2: Failure (timed out, no datagram sent).

Library

UDP.LIB

See Also

udp_sendto, udp_recvfrom, udp_bypass_arp

2.9 Macros


DISABLE_DNS


This macro disables DNS lookup. This prevents a UDP socket for DNS from being allocated, thus saving memory. Users may still call resolve() with an IP address.


MAX_SOCKETS


This macro defines the number of sockets that will be allocated, not including the socket for DNS lookups. It defaults to 4. If libraries such as HTTP.LIB or FTP_SERVER.LIB are used, you must provide enough sockets in MAX_SOCKETS for them also. This macro has been replaced by MAX_TCP_SOCKET_BUFFERS and MAX_UDP_SOCKET_BUFFERS.


MAX_SOCKET_LOCKS


For µC/OS-II support. This macro defines the number of socket locks to allocate. It defaults to MAX_TCP_SOCKET_BUFFERS + MAX_UDP_SOCKET_BUFFERS.

This macro is necessary because we can no longer calculate the number of socket locks needed based on the number of socket buffers, now that the user can manage their own socket buffers.


MAX_TCP_SOCKET_BUFFERS


Starting with Dynamic C version 7.05, this macro determines the maximum number of TCP sockets with preallocated buffers. If MAX_SOCKETS is defined, then MAX_TCP_SOCKET_BUFFERS will be assigned the value of MAX_SOCKETS for backwards compatibility. If neither macro is defined, MAX_TCP_SOCKET_BUFFERS defaults to 4.


MAX_UDP_SOCKET_BUFFERS


Starting with Dynamic C version 7.05, this macro determines the maximum number of UDP sockets with preallocated buffers. It defaults to 0.


MY_DOMAIN


This macro is the initial value for the domain portion of the controller's address. At runtime, it can be overwritten by tcp_config() and setdomainname().


MY_GATEWAY


This macro gives the default value for the controllers default gateway. At runtime, it can be overwritten by tcp_config().


MY_IP_ADDRESS


This macro is the default IP address for the controller. At runtime, it can be overwritten by tcp_config() and sethostid().


MY_NAMESERVER


This macro is the default value for the primary name server. At runtime, it can be overwritten by tcp_config().


MY_NETMASK


This macro is the default netmask for the controller. At runtime, it can be overwritten by tcp_config().


SOCK_BUF_SIZE


This macro determines the size of the socket buffers. A TCP socket will have two buffers of size SOCK_BUF_SIZE/2 for send and receive. A UDP socket will have a single socket of size SOCK_BUF_SIZE. Both types of sockets take the same total amount of buffer space. This macro has been replaced by TCP_BUF_SIZE and UDP_BUF_SIZE.


TCP_BUF_SIZE


Starting with Dynamic C 7.05, TCP and UDP socket buffers are sized separately. TCP_BUF_SIZE defines the buffer sizes for TCP sockets. It defaults to 4096 bytes. Backwards compatibility exists with earlier version of Dynamic C: if SOCK_BUF_SIZE is defined, TCP_BUF_SIZE is assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then TCP_BUF_SIZE will be assigned the value of tcp_MaxBufSize*2.


tcp_MaxBufSize


This use of this macro is deprecated in Dynamic C version 6.57 and higher; it has been replaced by SOCK_BUF_SIZE.

In Dynamic C versions 6.56 and earlier, tcp_MaxBufSize determines the size of the input and output buffers for TCP and UDP sockets. The sizeof(tcp_Socket) will be about 200 bytes more than double tcp_MaxBufSize. The optimum value for local Ethernet connections is greater than the Maximum Segment Size (MSS). The MSS is 1460 bytes. You may want to lower tcp_MaxBufSize, which defaults to 2048 bytes, to reduce RAM usage. It can be reduced to as little as 600 bytes.

tcp_MaxBufSize will work slightly differently in Dynamic C versions 6.57 and higher. In these later versions the buffer for the UDP socket will be tcp_MaxBufSize*2, which is twice as large as before.


UDP_BUF_SIZE


Starting with Dynamic C 7.05, TCP and UDP socket buffers are sized separately. UDP_BUF_SIZE defines the buffer sizes for UDP sockets. It defaults to 4096 bytes. Backwards compatibility exists with earlier version of Dynamic C: if SOCK_BUF_SIZE is defined, UDP_BUF_SIZE is assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then UDP_BUF_SIZE will be assigned the value of tcp_MaxBufSize*2.


Z-World
http://www.zworld.com
Voice: 530.757.3737
Fax: 530.757.3792 or 530.753.5141
sales@zworld.com
PREV NEXT INDEX