.title TCPIP$UDP_CLIENT_QIO - Example UDP IPv4 Client .ident /V5.4-00/ ; ; © Copyright 1976, 2003 Hewlett-Packard Development Company, L.P. ; ; Confidential computer software. Valid license from HP and/or its ; subsidiaries required for possession, use, or copying. ; ; Consistent with FAR 12.211 and 12.212, Commercial Computer Software, ; Computer Software Documentation, and Technical Data for Commercial ; Items are licensed to the U.S. Government under vendor's standard ; commercial license. ; ; Neither HP nor any of its subsidiaries shall be liable for technical ; or editorial errors or omissions contained herein. The information ; in this document is provided "as is" without warranty of any kind ; and is subject to change without notice. The warranties for HP ; products are set forth in the express limited warranty statements ; accompanying such products. Nothing herein should be construed as ; constituting an additional warranty. ; ; ++ ; FACILITY: ; ; EXAMPLES ; ; ABSTRACT: ; ; This is an example of a UDP/IP IPv4 client using OpenVMS ; QIO system services from MACRO-32 to handle network I/O ; operations. ; ; Refer to 'Build, Configuration, and Run Instructions' for ; details on how to build, configure, and run this program. ; ; ENVIRONMENT: ; ; OpenVMS Alpha/VAX V7.1 ; TCP/IP Services V5.0 or higher ; ; AUTHOR: ; ; TCPIP Development Group, CREATION DATE: 23-May-1989 ; ; -- .sbttl Build, Configuration, and Run Instructions ; ++ ; BUILD INSTRUCTIONS: ; ; To build this example program use commands of the form, ; ; on OpenVMS ALPHA: ; ; $ librarian/create/macro TCPIP$INETDEF.MLB SYS$LIBRARY:TCPIP$INETDEF.MAR ; $ macro/migration TCPIP$UDP_CLIENT_QIO.MAR + TCPIP$INETDEF.MLB/library ; $ link TCPIP$UDP_CLIENT_QIO ; ; on OpenVMS VAX: ; ; $ librarian/create/macro TCPIP$INETDEF.MLB SYS$LIBRARY:TCPIP$INETDEF.MAR ; $ macro TCPIP$UDP_CLIENT_QIO.MAR + TCPIP$INETDEF.MLB/library ; $ link TCPIP$UDP_CLIENT_QIO ; ; ; CONFIGURATION INSTRUCTIONS: ; ; No special configuration required. ; ; ; RUN INSTRUCTIONS: ; ; To run this example program: ; ; 1) Start the client's server program as shown below: ; ; $ run tcpip$udp_server_qio ; Waiting for a client datagram on port: m ; ; 2) After the server program blocks, start this client program, ; entering the server host as shown below: ; ; $ run tcpip$udp_client_qio ; Enter remote host: ; ; Note: You can specify a server host by using either an IPv4 ; address in dotted-decimal notation (e.g. 16.20.10.56) ; or a host domain name (e.g. serverhost.hp.com). ; ; 3) The client program then displays server address information ; and server data as shown below: ; ; Sent a datagram to host: a.b.c.d, port: n ; Data sent: Hello, world! ; ; You can enter "ctrl/z" at any user prompt to terminate program ; execution. ; ; -- .sbttl Module Declarations ; ; INCLUDE FILES: ; ; 'starlet' library symbol definitions $efndef ; define 'EFN$C_ENF' event flag ; 'tcpip$inetdef' library symbol definitions $hostentdef ; define hostent structure $inetsymdef ; define ipv4 related constants $sockaddrindef ; define ipv4 socket address structure ; ; EQUATED SYMBOLS: ; inaddr_none = -1 ; invalid address return status code ; for decc$inet_addr socket routine serv_portnum = 12345 ; server port number ; ; LOCAL STORAGE: ; .psect data,noexe ; ; miscellaneous data structures ; buffer: .blkb 512 ; i/o buffer buffer_len = .-buffer ; length of i/o buffer (in bytes) fao_buffer: .blkb 128 ; fao string buffer fao_buffer_len = .-fao_buffer ; length of fao buffer (in bytes) fao_desc: .quad 0 ; fao string descriptor getline_desc: .quad 0 ; user input string descriptor ; ; network i/o related structures ; inet_channel: .word 0 ; inet device i/o channel inet_device: ; string descriptor of logical .ascid /TCPIP$DEVICE:/ ; name of internet pseudodevice iosb: .quad 0 ; i/o status block udp_sockchar: ; udp socket characteristics buffer ; with following fields: .word tcpip$c_udp ; protocol .byte tcpip$c_dgram ; socket type .byte tcpip$c_af_inet ; address format ; ; server related structures ; serv_addr: ; server socket address structure ; with following fields: .word tcpip$c_af_inet ; server address format (ipv4) .word 0 ; server port number ; (in network byte order) .long 0 ; server ipv4 address ; (in network byte order) .byte 0[sin$s_zero] ; not used - must be zero serv_itemlst: ; server item-list 2 descriptor ; with following fields: .word sin$s_sockaddrin ; length .word 0 ; parameter type .address serv_addr ; server ipv4 address structure serv_port: .long serv_portnum ; server port no. (in host byte order) ; ; fao, error, and user prompt string storage ; fao$t_pktdata: .ascid \Hello, world!!\ fao$t_serveraddr: .ascid \Sent a datagram to host: !AZ, port: !UW\ fao$t_serverdata: .ascid \Data sent: !AZ\ msg$t_assignerr: .ascid \Failed to assign i/o channel to TCPIP device\ msg$t_closerr: .ascid \Failed to close socket\ msg$t_dassgnerr: .ascid \Failed to deassign i/o channel to TCPIP device\ msg$t_inputerr: .ascid \Failed to read user input\ msg$t_sockerr: .ascid \Failed to create socket\ msg$t_writerr: .ascid \Failed to write datagram to server\ prm$t_servaddr: .ascid \Enter remote host: \ .sbttl Client Main ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This is the client's main-line code. It handles all the tasks of the ; client including: socket creation, writing server data, and deleting ; the socket. ; ; This example program implements a typical UDP IPv4 client using QIO ; system services to handle network i/o operations as shown below: ; ; 1) To create a socket: ; ; sys$assign() and sys$qiow(IO$_SETMODE) ; ; 2) To transfer data: ; ; sys$qiow(IO$_WRITEVBLK) ; ; 3) To close and delete a socket: ; ; sys$qiow(IO$_DEACCESS) and sys$dassgn() ; ; CALLING SEQUENCE: ; ; This routine is invoked by the DCL "RUN" command. ; ; INPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT INPUTS: ; ; buffer - i/o buffer ; inet_channel - inet device i/o channel ; inet_device - inet device logical name ; iosb - i/o status block ; serv_addr - server socket address structure ; serv_itemlst - server item-list 2 descriptor ; serv_port - server port number ; udp_sockchar - udp socket characteristics buffer ; ; OUTPUT PARAMETERS: ; ; r0 - completion status ; ; IMPLICIT OUTPUTS: ; ; ** None ** ; ; ROUTINE VALUE: ; ; ss$_normal - program completed successfully ; ss$_noiochan - no available i/o channel ; ss$_unreachable - remote host unreachable ; ; SIDE EFFECTS: ; ; ** None ** ; ; -- .psect $code,exe .entry start,^m<> ; ; convert server port to network-byte order and ; store in server's socket address structure ; pushl serv_port ; pass server port calls #1,g^decc$htons ; get server port in network-byte order movab serv_addr,r1 ; get base of socket address structure movw r0,sin$w_port(r1) ; store server port ; ; get server host address from user ; pushab serv_addr ; pass server socket address structure calls #1,get_servaddr ; ask user for server host address ; ; assign device socket ; $assign_s - ; devnam = inet_device, - ; inet device logical name chan = inet_channel ; inet device i/o channel blbs r0,create ; if lbs, assigned device socket pushaq msg$t_assignerr ; error occurred - inform user of calls #1,put_errmsg ; device socket error brw exit ; before returning to caller ; ; create udp socket ; create: $qiow_s efn = #efn$c_enf, - ; event flag chan = inet_channel, - ; i/o channel func = #io$_setmode, - ; i/o function code iosb = iosb, - ; i/o status block p1 = udp_sockchar ; p1 - socket characteristics buffer blbc r0,10$ ; if lbc, error creating socket blbs iosb,write ; if lbs, created socket movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_sockerr ; error occurred - inform user of calls #1,put_errmsg ; socket creation error brw exit ; before returning to caller ; ; write a datagram to server ; write: pushab fao$t_pktdata ; pass string to format server data calls #1,format_servdata ; format server data $qiow_s efn = #efn$c_enf, - ; event flag chan = inet_channel, - ; i/o channel func = #io$_writevblk,- ; i/o function code iosb = iosb, - ; i/o status block p1 = buffer, - ; p1 - buffer address p2 = #buffer_len, - ; p2 - buffer length p3 = #serv_itemlst ; p3 - remote socket name blbc r0,10$ ; if lbc, error writing to server blbs iosb,20$ ; if lbs, write to server completed movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_writerr ; error occurred - inform user of calls #1,put_errmsg ; server datagram write error brw exit ; before returning to caller 20$: pushab serv_addr ; pass server's socket address structure calls #1,put_servaddr ; output server's address information pushab buffer ; pass server's data buffer calls #1,put_servdata ; output server's data buffer ; ; close udp socket ; close: $qiow_s efn = #efn$c_enf, - ; event flag chan = inet_channel, - ; i/o channel func = #io$_deaccess, - ; i/o function code iosb = iosb ; i/o status block blbc r0,10$ ; if lbc, close on socket failed blbs iosb,deassign ; if lbs, socket closed movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_closerr ; error occurred - inform user of calls #1,put_errmsg ; socket close error brw exit ; before returning to caller ; ; deassign device socket ; deassign: $dassgn_s - ; deassign device socket chan = inet_channel ; blbs r0,10$ ; if lbs, device socket released pushaq msg$t_dassgnerr ; otherwise, error occurred calls #1,put_errmsg ; inform user of deassign error brw exit ; before returning to caller ; ; return with success/error status ; 10$: movzbl #ss$_normal,r0 ; set success status exit: ret ; return to caller .sbttl Get Server Host Address ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine prompts the user and reads from sys$input the server's ; host address and stores it in the server's socket address structure. ; Note that the user can specify a server host by using either an IPv4 ; address in dotted-decimal notation (e.g. 16.20.10.126) or a host ; domain name (e.g. serverhost.hp.com). ; ; Enter "ctrl/z" to terminate program execution. ; ; CALLING SEQUENCE: ; ; calls #1,get_servaddr ; ; INPUT PARAMETERS: ; ; 4(ap) - address of server's socket address structure ; ; IMPLICIT INPUTS: ; ; prm$t_servaddr - user prompt to get server's address ; ; OUTPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT OUTPUTS: ; ; buffer - i/o buffer ; getline_desc - user input string descriptor ; ; ROUTINE VALUE: ; ; ** None ** ; ; SIDE EFFECTS: ; ; 1. Contents of processor registers r0 & r1 are modified ; ; 2. Program execution is terminated if unable to read user's input ; ; -- .entry get_servaddr,^m 10$: movaq getline_desc,r2 ; get base of input string descriptor movzwl #buffer_len,(r2) ; set length of input string buffer movab buffer, - ; set address of input string buffer dsc$a_pointer(r2) ; ; ; prompt and read user's address input ; pushaw (r2) ; pass 'resultant-length' argument pushaq prm$t_servaddr ; pass 'prompt-string' argument pushaq (r2) ; pass 'resultant-string' argument calls #3,g^lib$get_input ; get server address from sys$input blbs r0,20$ ; if lbs, successfully read user input pushaq msg$t_inputerr ; error occurred - inform user of calls #1,put_errmsg ; input line error before $exit_s r0 ; terminating program execution 20$: movzwl (r2),r3 ; get length of user input string addl2 dsc$a_pointer(r2),r3 ; compute end of user input string clrb (r3) ; zero terminate user input string ; ; attempt to convert address string to a ipv4 address ; pushl dsc$a_pointer(r2) ; pass server address string calls #1,g^decc$inet_addr ; convert string to ipv4 address cmpl r0,#inaddr_none ; valid ipv4 address? bnequ 30$ ; if nequ, yes ; ; if user input string isn't a valid dotted-decimal address ; then search network database for a matching domain name ; pushl dsc$a_pointer(r2) ; pass server address string calls #1,g^decc$gethostbyname ; search for matching domain name tstl r0 ; find a matching domain name? beqlu 10$ ; if eqlu, no - user must try again movl host$l_h_addr(r0),r0 ; get 'h_addr_list' member of hostent movl (r0),r0 ; get pointer table entry movl (r0),r0 ; get ipv4 address entry ; ; store address in server's socket address structure ; 30$: movl 4(ap),r3 ; get base of socket address structure movl r0,sin$l_addr(r3) ; store user selected server address ret ; return to caller .sbttl Format Server Data ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine formats the server's packet data buffer. ; ; CALLING SEQUENCE: ; ; calls #1,format_servdata ; ; INPUT PARAMETERS: ; ; 4(ap) - address of control string to format server packet data buffer ; ; IMPLICIT INPUTS: ; ; ** None ** ; ; OUTPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT OUTPUTS: ; ; buffer - i/o buffer ; fao_desc - fao string descriptor ; ; ROUTINE VALUE: ; ; ** None ** ; ; SIDE EFFECTS: ; ; Contents of processor registers r0 & r1 are modified ; ; -- .entry format_servdata,^m movaq fao_desc,r6 ; get base of fao string descriptor movzwl #buffer_len,(r6) ; set length of fao string buffer movab buffer, - ; set address of fao string buffer dsc$a_pointer(r6) ; movc5 #0,@dsc$a_pointer(r6),- ; set fao string buffer to all 0's #0, - ; (r6),@dsc$a_pointer(r6) ; pushaq (r6) ; pass fao's 'outbuf' argument pushaw (r6) ; pass fao's 'outlen' argument pushl 4(ap) ; pass fao's 'ctrstr' argument calls #3,g^sys$fao ; format server packet data for output ret ; return to caller .sbttl Output Server Address Info ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine outputs to sys$output the server host's address info ; consisting of: ; ; a) server ipv4 address ; b) server port number ; ; CALLING SEQUENCE: ; ; calls #1,put_servaddr ; ; INPUT PARAMETERS: ; ; 4(ap) - address of server's ipv4 socket address structure ; ; IMPLICIT INPUTS: ; ; fao$t_serveraddr - control string to format server address info ; ; OUTPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT OUTPUTS: ; ; fao_buffer - fao string buffer ; fao_desc - fao string descriptor ; ; ROUTINE VALUE: ; ; ** None ** ; ; SIDE EFFECTS: ; ; Contents of processor registers r0 & r1 are modified ; ; -- .entry put_servaddr,^m movaq fao_desc,r2 ; get base of fao string descriptor movzwl #fao_buffer_len,(r2) ; set length of fao string buffer movab fao_buffer, - ; set address of fao string buffer dsc$a_pointer(r2) ; movl 4(ap),r3 ; get base of socket address structure movzwl sin$w_port(r3),-(sp) ; isolate server's port no. calls #1,g^decc$ntohs ; get port no. in host-byte order pushl r0 ; pass server's port no. pushl sin$l_addr(r3) ; isolate server's ipv4 address calls #1,g^decc$inet_ntoa ; convert ipv4 address to string pushl r0 ; pass server's ipv4 address string pushaq (r2) ; pass fao's 'outbuf' argument pushaw (r2) ; pass fao's 'outlen' argument pushaq fao$t_serveraddr ; pass fao's 'ctrstr' argument calls #5,g^sys$fao ; format address info for output pushaq (r2) ; pass descriptor of string to output calls #1,g^lib$put_output ; output address info to sys$output ret ; return to caller .sbttl Output Server Data ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine outputs to sys$output the server data buffer. ; ; CALLING SEQUENCE: ; ; calls #1,put_servdata ; ; INPUT PARAMETERS: ; ; 4(ap) - address of server data buffer ; ; IMPLICIT INPUTS: ; ; fao$t_serverdata - control string to format server data buffer ; ; OUTPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT OUTPUTS: ; ; fao_buffer - fao string buffer ; fao_desc - fao string descriptor ; ; ROUTINE VALUE: ; ; ** None ** ; ; SIDE EFFECTS: ; ; Contents of processor registers r0 & r1 are modified ; ; -- .entry put_servdata,^m movaq fao_desc,r2 ; get base of fao string descriptor movzwl #fao_buffer_len,(r2) ; set length of fao string buffer movab fao_buffer, - ; set address of fao string buffer dsc$a_pointer(r2) ; pushl 4(ap) ; pass base of server data buffer pushaq (r2) ; pass fao's 'outbuf' argument pushaw (r2) ; pass fao's 'outlen' argument pushaq fao$t_serverdata ; pass fao's 'ctrstr' argument calls #4,g^sys$fao ; format server data buffer for output pushaq (r2) ; pass descriptor of string to output calls #1,g^lib$put_output ; output server data to sys$output ret ; return to caller .sbttl Output Error Message ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine outputs error messages to sys$output without modifying ; the contents of process register r0. ; ; CALLING SEQUENCE: ; ; calls #1,put_errmsg ; ; INPUT PARAMETERS: ; ; 4(ap) - address of error message string ; ; IMPLICIT INPUTS: ; ; ** None ** ; ; OUTPUT PARAMETERS: ; ; ** None ** ; ; IMPLICIT OUTPUTS: ; ; ** None ** ; ; ROUTINE VALUE: ; ; ** None ** ; ; SIDE EFFECTS: ; ; ** None ** ; ; -- .entry put_errmsg,^m<> pushl r0 ; save process register r0 pushl 4(ap) ; pass base of error message string calls #1,g^lib$put_output ; output error message to sys$output popl r0 ; restore processor register r0 ret ; return to caller .end start