DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Developing applications over NetBIOS using XTI

Example NetBIOS client code

1  /*
2   * Example NetBIOS client
3   */

4 #include <stdio.h> 5 #include <fcntl.h> 6 #include <xti.h> 7 #include <sys/nb/nbtpi.h>

8 #define SRV_NAME "NB-XTI-DEMO-SERV" 9 #define RFCNBPATH "/dev/nbcots" 10 #define NBEPATH "/dev/netbeui"

11 extern int t_errno;

12 main (int argc, char *argv[]) 13 { 14 int rval; 15 int flags = 0; 16 char *netpath = RFCNBPATH; 17 int fd; 18 int nbytes; 19 struct t_call *sndcall; 20 struct nbaddr srv_addr; 21 struct { 22 unsigned short length; 23 char buf[1024]; 24 } msg;

25 if ((fd = t_open(netpath, O_RDWR, (struct t_info *) NULL)) < 0) { 26 t_error("t_open failed"); 27 exit(1); 28 }

29 if (t_bind(fd, (struct t_bind *) NULL, 30 (struct t_bind *) NULL) < 0) { 31 t_error("t_bind error"); 32 exit(2); 33 }

34 if ((sndcall = 35 (struct t_call *)t_alloc(fd, T_CALL, T_ADDR)) == NULL) { 36 t_error("t_alloc failed"); 37 exit(3); 38 }

39 sndcall->addr.len = sizeof(srv_addr); 40 sndcall->addr.buf = (char *)&srv_addr; 41 srv_addr.nb_type = NB_UNIQUE; 42 memcpy(srv_addr.nb_name, SRV_NAME, NB_NAMELEN);

43 if (t_connect(fd, sndcall, (struct t_call *) NULL) < 0) { 44 t_error("t_connect failed for fd"); 45 rval = t_look(fd); 46 if(rval) 47 fprintf(stderr, "t_look returned event %d\n", rval); 48 exit(4); 49 }

50 while ((nbytes = t_rcv(fd, (char *)&msg, sizeof(msg), &flags)) >= 51 sizeof(msg.length)) { 52 if (fwrite(msg.buf, 1, msg.length, stdout) < 0) { 53 fprintf(stderr, "fwrite failed"); 54 exit(5); 55 } 56 if (msg.length == 0) 57 break; 58 }

59 if (nbytes == sizeof(msg.length) && msg.length == 0) { 60 if (t_snddis(fd, NULL) < 0) { 61 t_error("t_snddis failed"); 62 exit(6); 63 } 64 exit(0); 65 }

66 if (nbytes < sizeof(msg.length)) { 67 fprintf(stderr, "received invalid message, hanging up"); 68 t_snddis(fd, (struct t_call *) NULL); 69 exit(7); 70 } 71 else { 72 if (t_errno == TLOOK) { 73 if (t_look(fd) == T_DISCONNECT) { 74 printf("Got T_DISCONNECT, doing t_rcvdis"); 75 if (t_rcvdis(fd, (struct t_discon *) NULL) < 0) { 76 t_error("t_rcvdis failed"); 77 exit(8); 78 } 79 exit(0); 80 } 81 } 82 else { 83 t_error("t_rcv failed"); 84 exit(9); 85 } 86 } 87 }


line 5
includes the header file that defines the flags O_RDWR and O_NONBLOCK that can be passed in the flags argument to t_open (see line 25).

line 8
defines the name used to identify the server. Replace the string in this line with the name of the server on your network.

line 9
defines a symbol for the device name of the connection-oriented SCO TCP/NetBIOS transport.

line 10
defines a symbol for the device name of the connection-oriented NetBEUI transport.

line 11
declares the global variable used by all XTI routines to report an error.

line 15
initializes the flags argument that will be passed into t_rcv.

line 16
assigns the device name of the transport provider to open. Use the value NBEPATH (instead of RFCNBPATH) to access NetBEUI.

line 20
declares the variable that will contain the NetBIOS name of the server to be contacted.

lines 21-24
declare the data structure defined by this application for each chunk of data to be received. The buf field is a buffer to hold 1K of data. The length field is used to implement in the application itself a client/server handshake equivalent to orderly release.

line 25
opens a connection-oriented transport endpoint (netpath) with full duplex communication (O_RDWR). Because O_NONBLOCK is not specified along with O_RDWR, t_connect and t_rcv will block until either they succeed or an error is detected. To specify both O_RDWR and O_NONBLOCK, you would code
   t_open(netpath, O_NONBLOCK | O_RDWR, (struct t_info *)NULL)

lines 29-30
let the transport provider bind whatever name it chooses to the transport endpoint (the first NULL), and the client does not care to be informed what name was chosen (the second NULL). This is the normal case for a client.

lines 34-35
allocate a struct t_call data structure. The fields of the structure will be assigned the NetBIOS address information.

line 39
initializes the length field of the struct netbuf data structure.

line 40
initializes the pointer field in the struct netbuf data structure with the address of the buffer where the NetBIOS address information will be stored.

line 41
indicates that the name of the server to be contacted is a unique name, not a group name.

line 42
initializes the name field of the struct nb_addr structure with the name of the server.

line 43
connects to the server.

line 50
reads nbytes of data through the transport endpoint. The first two bytes are read into msg.length. The remaining bytes are read into msg.buf.

line 52
writes msg.length bytes of data from msg.buf to the standard output.

lines 56-65
check if the number of bytes sent was zero. This is the signal from the server that no more data will be sent. The client then exits normally. This is the protocol used by this sample application to implement the semantics of orderly release over a transport provider (NetBIOS) that provides only an abortive disconnect (using t_snddis).

lines 66-70
check if the client received the length field of the message. If not, something went wrong. The client bails out by disconnecting. A more robust client might implement an error recovery mechanism.

lines 72-81
check if an asynchronous event has occurred. If the client has received a disconnect request, it consumes the event by calling t_rcvdis, then exits normally (line 79).

lines 83-84
implement the client's error recovery algorithm. This code is reached only if an error has occurred on the call to t_rcv on line 50. The client could check what error has occurred by examining the value of t_errno. In this example, the client simply gives up.

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004