| # ITK Programmer's Guide
Table of contents | Intro | General | TCP Low Level | TCP High Level | UDP | DNS | PPP Encoding/Decoding | Internet Config | Goodies | Cryptography & SSL | Appendix
Chapter 3 : Low-level TCP/IP routines
Chapter contents: |
ITK_TCPOpen ITK_TCPListen ITK_TCPClose ITK_TCPRelease ITK_TCPStatus ITK_TCPStatus2A | ITK_TCPSend ITK_TCPRcv ITK_TCPChRcv ITK_TCPUnRcv ITK_TCPStrmInfo ITK_TCPWaitConn ITK_SetTimeout
About this chapter... | This chapter describes the basic TCP/IP routines provided by ITK. These routines allow to open connections (streams) between two computers using the TCP/IP protocol to transfer data reliably.

ITK_TCPOpen
Syntax: | streamRef := ITK_TCPOpen (hostName;remotePort;rcvBuffer;tcpOpt;oldStream;localPort;localIP)
Warning: | All streams opened using ITK_TCPOpen MUST be released using ITK_TCPRelease .
Description: | Opens a TCP stream asynchronously (returns control immediately without waiting for the connection to be established with the remote host). Use ITK_TCPStatus or ITK_TCPWaitConn to wait for the connection to be established. Use tcpOpt to open an SSL "client" stream instead of a plain TCP stream (added in ITKv2.5). This option is only available in the "Pro" version of ITK. If remotePort is equal to 443 (HTTPS standard port number), ITK will switch automatically to SSL.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | hostName | String | TCP address of remote host | "www.internet-toolkit.com" or "194.2.244.11" See Note#1
-> | remotePort | Integer | TCP remote port | ex: 80 for HTTP, 25 for SMTP. See RFC#1700 for assigned numbers.
-> | rcvBuffer | Longint | Buffer size for this stream (in bytes) | This parameter is used only under MacTCP. Accepts values between 8192 and 32767. Pass 0 for ITK to use a default buffer of 8KB (8192 bytes).
-> | tcpOpt | Longint | TCP options (type of service field, leave 0 as default) | This parameter is used only under MacTCP. See MacTCP Programmer's Manual for more details on the "type of service" values. option 1024 indicates that an SSL "client" stream should be opened instead of a classical TCP stream (added in ITKv2.5)
-> | oldStream | Longint | old stream reference number to reuse (set to 0 to allocate a new stream) | This parameter is obsolete and shouldn't be used anymore.
-> | localPort | Integer | local port number | Pass 0 for ITK to choose a local port number.
-> | localIP | Longint | local IP address This parameter is provided for multihoming support. |
<- | streamRef | Longint | stream reference number | Will return 0 if the stream couldn't be created.
Note#1: if you add a "." at the beginning of the TCP address of the remote host (ex: ".www.internet-toolkit.com"), ITK will choose randomly one of the resolved addresses returned by the DNS to do DNS load balancing (see ITK_Name2Addr for more information).
Example: |
    ` open a stream with an HTTP server
    $stream := ITK_TCPOpen("www.internet-toolkit.com";80)
    If ($stream#0)
      ...
      $err := ITK_TCPRelease($stream)
    End If

    ` open an SSL stream with an HTTPS server
    $stream := ITK_TCPOpen("www.internet-toolkit.com";443;0;1024) ` SSL stream
    If ($stream#0)
      ...
      $err := ITK_TCPRelease($stream)
    End If

Back to top

ITK_TCPListen
Syntax: | streamRef := ITK_TCPListen (hostFilter; portFilter; localPort; rcvBuffer; tcpOpt; oldStream; localIP)
Warning: | All streams opened using ITK_TCPListen MUST be released using ITK_TCPRelease .
Description: | Opens a "passive" or "listening" TCP stream to receive calls. Like in ITK_TCPOpen, control is returned immediately without waiting for a connection to be received and established. Use ITK_TCPStatus or ITK_TCPWaitConn to wait for the connection to be established. Use tcpOpt to create an SSL "server" stream instead of a TCP stream (added in ITKv2.5). If localPort is equal to 443 (HTTPS standard port number), ITK will switch automatically to SSL. SSL "server" is only available in the "Pro" version of ITK with an additional SSL server license.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | hostFilter | Longint | TCP address of remote host | Pass 0 to accept connections from any remote host, otherwise pass a numeric IP address to only accept connections from the specified remote host.
-> | portFilter | Integer | TCP remote port | Pass 0 to accept connections from any remote port numbers, otherwise pass a port number to only accept connections from the specified port number (ex: 80 for HTTP, 25 for SMTP, see RFC#1700 for assigned numbers).
-> | localPort | Integer | local port number | Pass the local port number on which you want to listen for incoming connections (ex: 80 for HTTP, 25 for SMTP, see RFC#1700 for assigned numbers).
-> | rcvBuffer | Longint | Receive buffer size for this stream | This parameter is used only under MacTCP. Accepts values between 8192 and 32767. Pass 0 for ITK to use a default buffer of 8KB (8192 bytes).
-> | tcpOpt | Longint | TCP options (type of service field, leave 0 as default) | This parameter is used only under MacTCP. See MacTCP Programmer's Manual for more details on the "type of service" values. option 2048 indicates that an SSL "server" stream should be created instead of a classical TCP stream (added in ITKv2.5)
-> | oldStream | Longint | old stream reference number to reuse (pass 0 to allocate a new stream) | This parameter is obsolete and shouldn't be used anymore.
-> | localIP | Longint | local IP address This parameter is provided for multihoming support. | Pass 0 if you want to accept incoming connections on all local IP addresses, otherwise, pass one of the local IP addresses to only accept incoming connection on the specified IP address.
<- | streamRef | Longint | stream reference number | Will return 0 if the stream couldn't be created.
Example: |
    ` create a TCP listening stream on HTTP port
    $stream := ITK_TCPListen(0;0;80) ` listen on HTTP port number
    If ($stream#0)
      ...
      $err := ITK_TCPRelease($stream)
    End If

    ` create an SSL listening stream on HTTPS port
    $stream := ITK_TCPListen(0;0;443;0;2048) ` listen on HTTPS port number
    If ($stream#0)
      ...
      $err := ITK_TCPRelease($stream)
    End If

Back to top

ITK_TCPClose
Syntax: | error := ITK_TCPClose (streamRef)
Description: | Sends the data remaining in the output buffer (see ITK_TCPSend ) and tells the remote host that no more data will be sent. After closing a stream, you can still receive data on it until you use ITK_TCPRelease . This is possible because a TCP stream is made of two half streams, each one used to send data from one host to the other. Each half-stream can be closed separately (also called half-close).
Warning: | Closing a stream doesn't releases the stream, but only tells the remote host that you're done sending data.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
<- | error | Longint | error code | 0 = no error -1 = invalid stream reference number
Example: |
    $stream := ITK_TCPOpen("www.internet-toolkit.com";80)
    If ($stream#0)
      ...
      $err := ITK_TCPClose($stream)
      ...
      $err := ITK_TCPRelease($stream)
    End If

Back to top

ITK_TCPRelease
Syntax: | error := ITK_TCPRelease (streamRef; optionFlag)
Description: | Releases a TCP stream and all its associated buffers. After this call, the streamRef should not be used anymore.
Note: | When calling ITK_TCPRelease , all data remaining to be sent will not be sent. To avoid this, you must call ITK_TCPClose and then monitor ITK_TCPStatus to check that the remote host has received all remaining data and that you closed your half-stream. Each successfull calls to ITK_TCPOpen and ITK_TCPListen must be balanced by a call to ITK_TCPRelease.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | optionFlag | Longint | Optionnal flag | 0 = no option 1 = obsolete flag 2 = force internal listener to stop listening
<- | error | Longint | error code | 0 = no error -1 = invalid stream reference number
Example: |
    $stream := ITK_TCPOpen("www.internet-toolkit.com";80)
    If ($stream#0)
      ...
      $err := ITK_TCPRelease($stream)
    End If

Back to top

ITK_TCPStatus
Syntax: | status := ITK_TCPStatus (streamRef;selector)
Description: | Returns the current status of a TCP stream or miscellaneous information about the stream. Use it to wait for a connection to be established (status=8) or for the remote host to acknowledge a half-close.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number or global info selector | Stream reference number as returned by ITK_TCPOpen , or ITK_TCPListen . Global info selectors: -1 = round trip average* -2 = minimum round trip time* -3 = maximum round trip time* -4 = maximum TCP segment size* -5 = maximum TCP connections -6 = number of connection attempts -7 = number of connections opened -8 = number of connections accepted -9 = number of closed connections -10 = number of aborted connections -11 = bytes received -12 = bytes sent -13 = duplicate bytes received* -14 = retransmitted bytes* -15 = number of packets received* -16 = number of packets sent* -17 = number of duplicate packets received* -18 = number of packets retransmitted* * information only available under MacTCP.
-> | selector | Longint | selector value | 0 = ITK_TCPStatus will return the current status of streamRef 1 = sendWindow will be returned* 2 = rcvWindow will be returned* 3 = amtUnackedData will be returned* 4 = amtUnreadData will be returned* 5 = sendUnacked will be returned* 6 = sendNext will be returned* 7 = congestionWindow will be returned* 8 = rcvNext* 9 = srtt* 10 = lastRTT* 11 = dataPktsRcvd* 12 = dataPktsSent* 13 = dataPktsResent* 14 = bytesRcvd** 15 = bytesRcvdDup* 16 = bytesRcvdPastWindow* 17 = bytesSent** 18 = bytesResent* 19 = lastRTT* 20 = tmrSRTT* 21 = rttVariance* 22 = tmrRTO* 23 = SSLrawRcvd** 24 = SSLrawSent** * information only available under MacTCP. **With SSL streams, bytesRcvd and bytesSent indicate the number of SSL data transmitted, SSLrawRcvd and SSLrawSent indicate the total raw bytes of encrypted data really transmitted at the TCP/IP layer level.
<- | status | Longint | current stream status code | -1 = invalid streamRef error other negative values = any other error Positive values are current status:
0 | Closed | no connection exists on this stream
2 | Listen | listening for an incoming connexion.
4 | SYN received | incoming connection is being established
6 | SYN sent | outgoing connection is being established
8 | Established | connection is up
10 | FIN Wait 1 | connection is up; close has been sent
12 | FIN Wait 2 | connection is up; close has been sent and acknowledged
14 | Close Wait | connection is up; close has been received
16 | Closing | connection is up; close has been issued and received
18 | Last ACK | connection is up; close has been issued and received
20 | Time Wait | connection is being broken
see RFC#793, page 21
Example: |
    ` wait for the connection to be established
    Repeat
      $s := ITK_TCPStatus($stream)
      IDLE
    Until (($s>=8) | ($s<0))  ` end if connected or error

Back to top

ITK_TCPStatus2A
Syntax: | index := ITK_TCPStatus2A (arrStreams;arrStatus;minStatus)
Description: | Returns the current status of an array of streams and the index of the first stream which status is greater than or equal to minStatus, or negative (error on the stream). This routine can be used to monitor the status of a list of streams and wait for a connection or a close to be acknowledged.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | arrStreams | Array of Longint | a list of stream reference numbers | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | arrStatus | Array of Longint | selector value | -1 = invalid streamRef error other negative value = any other error Positive values are current status:
0 | Closed | no connection exists on this stream
2 | Listen | listening for an incoming connexion.
4 | SYN received | incoming connection is being established
6 | SYN sent | outgoing connection is being established
8 | Established | connection is up
10 | FIN Wait 1 | connection is up; close has been sent
12 | FIN Wait 2 | connection is up; close has been sent and acknowledged
14 | Close Wait | connection is up; close has been received
16 | Closing | connection is up; close has been issued and received
18 | Last ACK | connection is up; close has been issued and received
20 | Time Wait | connection is being broken
see RFC#793, page 21
-> | minStatus | Longint | status value to reach |
<- | index | Longint | first item in array to reach | Will return the item number of the first stream that reaches minStatus or some error code (negative value).
Example: |
    ARRAY LONGINT($streams;10)
    ARRAY LONGINT($status;10)

    For ($i;1;10)
      $streams{$i} := ITK_TCPListen(0;0;80)
    End For

    ` wait for the connection to be established on a list of streams
    Repeat
      $i := ITK_TCPStatus2A($streams; $status; 8)
      If ($i>0)
        $s := ITK_TCPStatus($streams{$i})
        Case of
        :($s >= 8) ` stream connected
          ... ` handle the HTTP hit
        :($s<0) ` error on stream
          $err := ITK_TCPRelease($streams{$i})
          $streams{$i} := ITK_TCPListen(0;0;80)
        ...
        End Case
      End If
    Until (quit)

Back to top

ITK_TCPSend
Syntax: | result := ITK_TCPSend (streamRef;data;flushFlag;filterFlag)
Description: | Sends data through an established TCP stream. ITK has its own send buffer which helps reducing the number of calls to lower level TCP/IP layers when small chunks of data are sent. Filtering can be applied on the sent text.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | data | Text | data to send |
-> | flushFlag | Integer |  | 0 = don't use ITK output buffer, flush its content if it wasn't empty, 1 = use ITK's output buffer. It will be flushed regularly by ITK. Values above 255 indicate the maximum number of bytes that may be buffered. If the output buffer contains more than the value passed, ITK will flush its output buffer. ITK's send buffer will also be flushed when calling ITK_TCPRcv or ITK_TCPClose .
-> | filterFlag | Longint |  | One or more encodings can be applied before sending the data (or putting them in ITK's send buffer). You may add flag values to apply several filters. See Table#1 for all filter flag values.
-> | result | Longint |  | Returns the number of bytes currently stored in ITK's output buffer. Negative values indicates that an error occurred on this stream (it may have been released by the remote host).
Example: |
    $stream := ITK_TCPOpen("www.internet-toolkit.com";80)
    If ($stream#0)
      ... ` wait for connection to be established
      ` use ITK's send buffer
      $err := ITK_TCPSend($stream;"GET / HTTP/1.0"+$crlf;1)
      ` Flush ITK's send buffer
      $err := ITK_TCPSend($stream;"User-Agent: myWebBrowser/1.0"+$crlf+$crlf)
      ...

Back to top

ITK_TCPRcv
Syntax: | result := ITK_TCPRcv (streamRef;dataStorage;maxLen;filterFlag;appendFlag;endString;timeout)
Description: | Receives data through an established TCP stream. Remaining data in ITK's send buffer is sent if present. Filtering can be applied on the received text. ITK_TCPRcv will return control immediately when the timeout is set to 0. When the timeout is not 0, ITK_TCPRcv will return when one of these conditions is valid: endString (if not empty) is received (and according to the options flag), maxlen bytes have been received (if maxlen is not 0), data have been received and no maxlen is specified (or left to 0), timeout is over, the length of dataStorage is greater or equal to 32000 bytes.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | dataStorage | Text | storage variable or field | Content is replaced or appended depending on appendFlag
-> | maxLen | Integer | maximum length of data to be received | Pass 0 if you want to receive all available data (up to 32000 bytes which is the limit for Text fields or variables in 4D).
-> | filterFlag | Longint |  | One or more encodings can be applied before sending the data (or putting it into ITK's receive buffer). You may add flag values to apply several filters at once. See Table#1 for all filter flag values.
-> | options | Longint | Options can be combined, ex: 5 = 1+4 = append + search in new data | 0 = do not append received data to previous data present in dataStorage 1 = append received data to previous data present in dataStorage Version 2.0.3 and above: 2 = the ending string will remain in ITK's receive buffer 4 = do not search endstring in original data when append is used
-> | endString | String | end receive string | If this string is found in incoming data or accumulated data (when the append flag is used), ITK_TCPRcv will return all data up to this string (including it), remaining data will be kept in ITK's receive buffer.
-> | timeout | Longint | maximum time to wait for endString (in 1/60th of a second) | Special values: -1 = infinite time 0 = returns control immediately
<- | result | Longint | returns number of bytes received or any error code (negative value). | -1 = invalid stream reference number
Example: |
    $stream := ITK_TCPOpen("mail.internet-toolkit.com";25)
    if ($stream#0)
      ... ` wait for connection to be established
      $rcvdLen := ITK_TCPRcv($stream; $data)
      ...
In the following example, the first call to ITK_TCPRcv will receive data until a pair of CR/LF during a maximum of 2 minutes. Then the second call to ITK_TCPRcv will append received data into http_req until a <>CRLF is received in new data received or $len data are accumulated in http_req during a maximum of 2 minutes.
    ` Receive HTTP header
    $err := ITK_TCPRcv($c;http_req;32000;0;<>CRLF+<>CRLF; 2*60*60)
    ...
    If (http_req = "POST @")
      $err := ITK_TCPRcv($c;http_req;$len;1+4;<>CRLF;2*60*60) ` receive "POST" data
      ...

Back to top

ITK_TCPChRcv
Syntax: | result := ITK_TCPChRcv (streamRef)
Description: | Returns the number of bytes available in the receive buffer of a TCP stream.
Note: | The number of bytes received after calling ITK_TCPChRcv may be greater than the value returned by ITK_TCPChRcv as some data may have been received between the two calls.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
<- | result | Longint | number of bytes (positive values) or error code (negative values) | -1 = invalid stream reference number
Example: |
    if (ITK_TCPChRcv($stream)#0) ` do we have some data available ?
      $result := ITK_TCPRcv($stream;$buff)
      ...

Back to top

ITK_TCPUnRcv
Syntax: | result := ITK_TCPUnRcv (streamRef;data; options)
Description: | ITK_TCPUnRcv can be used to put some data you previously received back into ITK's receive buffer. This data will be received in the next call to receiving routines (like ITK_TCPRcv , ITK_TCPRcvBlob , ITK_TCPRcvFile , etc.).
Notes: | The options flags parameter has been added in v2.0.4.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | data | Text | data to put back in ITK's receive buffer |
-> | option | Longint | optional flags | 0 = put data at the END of the "unreceive buffer" 1 = put data at the BEGINING of the "unreceive buffer" Parameter added in v2.0.4
<- | result | Longint | error code | 0 = no error -1 = invalid stream reference number
Example: |
    $result := ITK_TCPRcv($stream; $data) ` receive some data
    if ($data # "+OK@")
      $err := ITK_TCPUnRcv($stream;$data) ` put it back in ITK's buffer to receive it again

Back to top

ITK_TCPStrmInfo
Syntax: | error := ITK_TCPStrmInfo (streamRef; remoteIP; remotePort; localPort; srtt; localIP)
Description: | Returns information about an established TCP stream.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
<- | remoteIP | Longint | IP address of the remote host | Content is replaced or appended depending on appendFlag
<- | remotePort | Integer | Port number used by the remote host | Pass 0 if you want to receive all available data (up to 32000 bytes which is the limit for Text fields or variables in 4D).
<- | localPort | Integer | Local port number | One or more encodings can be applied before sending the data (or putting it into ITK's receive buffer). You may add flag values to apply several filters at once. See Table#1 for all filter flag values.
<- | srtt | Longint | Smoothed round trip time | This value is only available under MacTCP, otherwise -1 is returned.
<- | localIP | Longint | Local IP address | This value is useful for multihomed systems (like Windows NT or MacOS with OpenTransport 1.3 or above). On non multihomed system, the local IP address is always returned.
<- | error | Longint |  | 0 = no error -1 = invalid stream reference number
Example: |
    $err := ITK_TCPStrmInfo($stream;remAddr;remPort;locPort;srtt;locAddr)
    ALERT("Remote host address: "+ITK_Addr2Name(remAddr;2))
Note: | localPort and remotePort may return negative values, because 4D is using signed integers. To get the original positive port number, you can use the following code: `C_LONGINT(locPort; remPort) `` `MUST` `be typed as LONGINTS !!! $err :=` `ITK_TCPStrmInfo` `($stream;remAddr;remPort;locPort;srtt;locAddr) If (locPort < 0) locPort := locPort + 65536 End if` `If (remPort < 0) remPort := remPort + 65536 End if`

Back to top

ITK_TCPWaitConn
Syntax: | result := ITK_TCPWaitConn (streamRef;minStatus;timeout)
Description: | Wait for a TCP stream to be in a certain status or to return an error (negative value). This routine can be used to wait for a stream to establish connection. This routine is synchronous, control will be returned: when the stream status is greater or equal to minStatus, when timeout expires, or when some error occurs with the stream.
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | minStatus | Longint | minimum status value to wait for |
-> | timeout | Longint | maximum time to wait (in seconds) | 0 = wait indefinitely
<- | result | Longint | stream's status or error code (negative values). | -1 = invalid stream reference number
Example: |
    $stream := ITK_TCPOpen("mail.internet-toolkit.com";25)
    ` wait for connection to be established
    $status := ITK_TCPWaitConn($stream;8;10) ` wait 10 seconds
    If ($status=8)
      ...
    End If
    $err := ITK_TCPRelease($stream)

Back to top

ITK_SetTimeout
Syntax: | curTimeout := ITK_SetTimeout (streamRef;newTimeout)
Description: | ITK_SetTimeout can be used to set the default timeout used by all "send" ITK routines (ITK_TCPSend, ITK_TCPSendFile, ITK_TCPSendPict, ITK_TCPSendBlob). By default, ITK doesn't use any timeout when sending data. It can be usefull to set a timeout to avoid possible "send locks" when the remote host becomes unreachable (crash or disconnection for example). When the send timeout is reached in one of the ITK_TCPSend routines, the routine will return control , but the status of the stream will remain the same. The best place to set the timeout for a given stream is just after a successfull call to ITK_TCPOpen or ITK_TCPListen .
Params: |
In/Out | Parameter | Type |  | Example or note
-> | streamRef | Longint | stream reference number | As returned by ITK_TCPOpen , or ITK_TCPListen .
-> | newTimeout | Longint | timeout value in seconds | 0 = no timeout (default ITK behaviour)
<- | curTimeout | Longint | new current timeout value (in seconds) |
Example: |
    $stream := ITK_TCPOpen("mail.internet-toolkit.com";25)
    if ($stream#0)
      ` all ITK_TCPSend calls will have a 2mn timeout
      $curTimeout := ITK_SetTimeout($stream;120)
      ...

Back to top

##### CQ/27-Mar-2001