.title TCPIP$UDP_SERVER_QIO - Example UDP IPv4 Server .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 server 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_SERVER_QIO.MAR + TCPIP$INETDEF.MLB/library ; $ link TCPIP$UDP_SERVER_QIO ; ; on OpenVMS VAX: ; ; $ librarian/create/macro TCPIP$INETDEF.MLB SYS$LIBRARY:TCPIP$INETDEF.MAR ; $ macro TCPIP$UDP_SERVER_QIO.MAR + TCPIP$INETDEF.MLB/library ; $ link TCPIP$UDP_SERVER_QIO ; ; ; CONFIGURATION INSTRUCTIONS: ; ; No special configuration required. ; ; ; RUN INSTRUCTIONS: ; ; To run this example program: ; ; 1) Start this server program as shown below: ; ; $ run tcpip$udp_server_qio ; Waiting for a client datagram om port: m ; ; 2) After the server program blocks, start the 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 server program then displays client address information ; and client data as shown below: ; ; Received a datagram from host: a.b.c.d, port: n ; Data received: 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 $inetsymdef ; define ipv4 related constants $sockaddrindef ; define ipv4 socket address structure $socketoptdef ; define socket option constants ; ; EQUATED SYMBOLS: ; 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 ; ; 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 ; ; client related structures ; client_addr: .blkb sin$s_sockaddrin ; client socket address structure client_itemlst: ; client item-list 3 descriptor ; with following fields: .word sin$s_sockaddrin ; length .word 0 ; parameter type .address client_addr ; client ipv4 address structure .address client_retlen ; address to return length of ; client socket address structure client_retlen: ; returned length of client socket .long 0 ; address structure ; ; 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 tcpip$c_inaddr_any ; server ipv4 address ; (accept connection on any interface) .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 tcpip$c_sock_name ; parameter type .address serv_addr ; server ipv4 address structure serv_port: .long serv_portnum ; server port no. (in host byte order) ; ; socket option related item-list descriptors/elements ; reuseaddr_val: .long 1 ; reuseaddr socket option value (on) reuseaddr_val_len = .-reuseaddr_val reuseaddr_itemlst: ; reuseaddr item-list 2 element ; with following fields: .word reuseaddr_val_len ; length .word tcpip$c_reuseaddr ; parameter type .address reuseaddr_val ; reuseaddr option value reuseaddr_itemlst_len = .-reuseaddr_itemlst sockopt_itemlst: ; socket option item-list 2 descriptor ; with following fields: .word reuseaddr_itemlst_len ; length .word tcpip$c_sockopt ; parameter type .address reuseaddr_itemlst ; reuseaddr item-list element ; ; fao and error string storage ; fao$t_clientaddr: .ascid \Received a datagram from host: !AZ, port: !UW\ fao$t_clientdata: .ascid \Data received: !AZ\ fao$t_servaddr: .ascid \Waiting for a client datagram on port: !UW\ msg$t_assignerr: .ascid \Failed to assign i/o channel to TCPIP device\ msg$t_binderr: .ascid \Failed to bind socket\ 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_readerr: .ascid \Failed to read datagram from client\ msg$t_sockerr: .ascid \Failed to create socket\ .sbttl Server Main ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This is the server's main-line code. It handles all the tasks of the ; server including: socket creation, binding a socket to the server's ; internet address and port, and reading client data. ; ; This example program implements a typical UDP IPv4 server using QIO ; system services to handle network i/o operations as shown below: ; ; 1) To create a socket and set REUSEADDR option: ; ; sys$assign() and sys$qiow(IO$_SETMODE) ; ; 2) To bind internet address and port number to a socket: ; ; sys$qiow(IO$_SETMODE) ; ; 3) To transfer data: ; ; sys$qiow(IO$_READVBLK) ; ; 4) 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 ; client_itemlst - client item-list 3 descriptor ; inet_channel - inet device i/o channel ; inet_device - inet device logical name ; iosb - i/o status block ; serv_itemlst - server item-list 2 descriptor ; serv_port - server port number ; sockopt_itemlst - socket option item-list 2 descriptor ; 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 no. 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 ; ; 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 p5 = #sockopt_itemlst ; p5 - socket options blbc r0,10$ ; if lbc, error creating udp socket blbs iosb,bind ; if lbs, created udp socket movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_sockerr ; error occurred - inform user of calls #1,put_errmsg ; udp socket creation error brw exit ; before returning to caller ; ; bind server's internet address and port number to socket ; bind: $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 p3 = #serv_itemlst ; p3 - local socket name blbc r0,10$ ; if lbc, error binding port to socket blbs iosb,read ; if lbs, bound port to socket movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_binderr ; error occurred - inform user of calls #1,put_errmsg ; error binding port to socket brw exit ; before returning to caller ; ; read a datagram from client; ; read: pushab serv_addr ; pass server's socket address structure calls #1,put_servaddr ; output server's address information $qiow_s efn = #efn$c_enf, - ; event flag chan = inet_channel, - ; i/o channel func = #io$_readvblk, - ; i/o function code iosb = iosb, - ; i/o status block p1 = buffer, - ; p1 - buffer address p2 = #buffer_len, - ; p2 - buffer length p3 = #client_itemlst ; p3 - remote socket name blbc r0,10$ ; if lbc, error reading from client blbs iosb,20$ ; if lbs, read from client completed movzwl iosb,r0 ; save i/o completion status 10$: pushaq msg$t_readerr ; error occurred - inform user of calls #1,put_errmsg ; client datagram read error brw exit ; before returning to caller 20$: pushab client_addr ; pass client's socket address structure calls #1,put_clientaddr ; output client's address information pushab buffer ; pass client's data buffer calls #1,put_clientdata ; output client's data buffer ; ; close udp socket ; close_server: $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 Output Client Address Info ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine outputs to sys$output the client host's address info ; consisting of: ; ; a) client ipv4 address ; b) client port number ; ; CALLING SEQUENCE: ; ; calls #1,put_clientaddr ; ; INPUT PARAMETERS: ; ; 4(ap) - address of client's ipv4 socket address structure ; ; IMPLICIT INPUTS: ; ; fao$t_clientaddr - control string to format client 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_clientaddr,^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 client's port no. calls #1,g^decc$ntohs ; get port no. in host-byte order pushl r0 ; pass client's port no. pushl sin$l_addr(r3) ; isolate client's ipv4 address calls #1,g^decc$inet_ntoa ; convert ipv4 address to string pushl r0 ; pass client's ipv4 address string pushaq (r2) ; pass fao's 'outbuf' argument pushaw (r2) ; pass fao's 'outlen' argument pushaq fao$t_clientaddr ; 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 Client Data ; ++ ; FUNCTIONAL DESCRIPTION: ; ; This routine outputs to sys$output the client data buffer. ; ; CALLING SEQUENCE: ; ; calls #1,put_clientdata ; ; INPUT PARAMETERS: ; ; 4(ap) - address of client data buffer ; ; IMPLICIT INPUTS: ; ; fao$t_clientdata - control string to format client 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_clientdata,^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 client data buffer pushaq (r2) ; pass fao's 'outbuf' argument pushaw (r2) ; pass fao's 'outlen' argument pushaq fao$t_clientdata ; pass fao's 'ctrstr' argument calls #4,g^sys$fao ; format client data buffer for output pushaq (r2) ; pass descriptor of string to output calls #1,g^lib$put_output ; output client data to sys$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 port number ; ; CALLING SEQUENCE: ; ; calls #1,put_serveraddr ; ; INPUT PARAMETERS: ; ; 4(ap) - address of server's ipv4 socket address structure ; ; IMPLICIT INPUTS: ; ; fao$t_servaddr - 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. pushaq (r2) ; pass fao's 'outbuf' argument pushaw (r2) ; pass fao's 'outlen' argument pushaq fao$t_servaddr ; pass fao's 'ctrstr' argument calls #4,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 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