CSa32/Node.S
changeset 0 5c129dd80d4f
equal deleted inserted replaced
-1:000000000000 0:5c129dd80d4f
       
     1 	.include "DS.S"
       
     2 	.data
       
     3 	.text
       
     4 #-----------------------------------------------
       
     5 #	N O D E   O P E R A T I O N S
       
     6 #-----------------------------------------------
       
     7 	ARGS
       
     8 	DS	CnstlnP				# -->Constellation inst
       
     9 	DS	port				# node's port#
       
    10 # returns
       
    11 #	nothing
       
    12 # local vars
       
    13 	PROLOC
       
    14 	DL	this, NodeL			# this Node instance
       
    15 	DL	thisP				# -->this Node
       
    16 	DL	deP				# -->Debug inst for LOG macro
       
    17 	DL	rc
       
    18 	DL	tosignal			# switch
       
    19 	DL	sigact, SigActionL
       
    20 	DL	sigmask, 128
       
    21 	DL	sigret
       
    22 	EPILOC
       
    23 #-----------------------------------------------
       
    24 	.global Node
       
    25 Node:
       
    26 	PROLOG
       
    27 	lea	this(bp), b			# -->this Node
       
    28 	mov	b, thisP(bp)			# save -->this Node
       
    29 	lea	N.debug(b), a
       
    30 	mov	a, deP(bp)			# save -->Debug locally for LOG macro
       
    31 # save parm values
       
    32 	mov	CnstlnP(bp), c			# -->Constellation
       
    33 	mov	c, N.cnstlnP(b)			# save -->Constellation
       
    34 	mov	port(bp), a
       
    35 	mov	a, N.locPort(b)			# save port#
       
    36 # set Debug id
       
    37 	push	a
       
    38 	cmpl	$Cn.ring, Cn.topo(c)
       
    39 	je	0f
       
    40 	push	$8f
       
    41 	jmp	1f
       
    42 0:	push	$7f
       
    43 1:	cmp	$0,Cn.ssl(c)
       
    44 	je	2f
       
    45 	push	$6f
       
    46 	jmp	9f
       
    47 2:	push	$5f
       
    48 	jmp	9f
       
    49 5:	.asciz	"non"
       
    50 6:	.asciz	""
       
    51 7:	.asciz	"RING"
       
    52 8:	.asciz	"MASH"
       
    53 9:	DEBID	"%sSSL %s node %d", 3		# N->ssl ? "" : "non", N.topo==mash ? "MASH" : "RING", locPort
       
    54 	call	N.init				# initialize node
       
    55 	call	N.bind				# bind node to local port
       
    56 	push	N.kicker(b)			# kicker indicator
       
    57 	LOG	5, "kicker=%d"
       
    58 	cmpl	$0, N.kicker(b) 		# kicker ?
       
    59 	je	0f				# no
       
    60 	call	N.kickOff			# start transfer
       
    61 0:
       
    62 	call	N.mainLoop			# iterate on socket I/O select
       
    63 	LOG	5, "closing ssc"
       
    64 	push	N.ssc(b)
       
    65 	SYS	close
       
    66 	movl	$0, rc(bp)			# rc = OK
       
    67 # wait on thread closing client side
       
    68 	cmpl	$0, N.closing(b)		# closing client side ?
       
    69 	je	N.chkData			# no
       
    70 	push	$0
       
    71 	push	N.ptid(b)			# thread id
       
    72 	call	pthread_join
       
    73 	test	a, a
       
    74 	jz	1f
       
    75 	push	a				# unique error handlig for pthread_join
       
    76 	call	strerror
       
    77 	push	a
       
    78 	LOG	0, "pthread_join: %s"
       
    79 	push	deP(bp)
       
    80 	call	C.abend
       
    81 1:
       
    82 	mov	thisP(bp), b			# -->this Node
       
    83 	push	N.pid(b)
       
    84 	LOG	5, "task %u: closing thread returned"
       
    85 # synchronize with all nodes in all constellations and then check received data
       
    86 N.chkData:
       
    87 	call	N.sync				# wait for others
       
    88 	cmpl	$0, N.kicker(b) 		# kicker ?
       
    89 	je	0f				# no
       
    90 
       
    91 	push	N.dataP(b)			# -->Data
       
    92 	call	Da.chk
       
    93 	test	a, a				# data check OK ?
       
    94 	jnz	0f				# yes
       
    95 	movl	$1, rc(bp)			# rc = BAD
       
    96 	LOG	0, "data on INPUT TO and OUTPUT FROM constellation DIFFER"
       
    97 0:
       
    98 	push	N.pid(b)
       
    99 	push	rc(bp)
       
   100 	LOG	2, "end of operations, rc=%d, process=%u"
       
   101 	call	exit
       
   102 #-----------------------------------------------
       
   103 #	C O N S T R U C T O R
       
   104 #-----------------------------------------------
       
   105 	PROLOC
       
   106 	DL	thisP				# -->this Node
       
   107 	DL	deP				# -->Debug
       
   108 #	DL	CnstlnP				# -->Constellation
       
   109 	DL	len				# various lengths
       
   110 	strL = 128
       
   111 	DL	str, strL			# string buf
       
   112 	EPILOC
       
   113 #-----------------------------------------------
       
   114 N.init:						# c: -->Cnstln
       
   115 	PROLOG
       
   116 	mov	b, thisP(bp)			# save -->this Node
       
   117 	lea	N.debug(b), a
       
   118 	mov	a, deP(bp)			# save local -->Debug
       
   119 	LOG	4, "initializing..."
       
   120 # initialize node's attributes
       
   121 	call	getpid
       
   122 	mov	a, N.pid(b)
       
   123 	mov	N.cnstlnP(b), c			# -->Constellation
       
   124 	push	deP(bp)				# -->caller Debug id
       
   125 	lea	N.data(b), a
       
   126 	mov	a, N.dataP(b)
       
   127 	push	a				# -->Data
       
   128 	call	Data				# initialize data item
       
   129 	mov	Cn.topo(c), a
       
   130 	mov	a, N.topo(b)			# save topology
       
   131 	mov	Cn.ssl(c), a
       
   132 	mov	a, N.ssl(b)			# SSL switch
       
   133 	mov	Cn.first(c), a
       
   134 	mov	a, N.first(b)			# save port# of first node in constellation
       
   135 	movl	$0, N.kicker(b)			# clear kicker switch
       
   136 	cmp	a, N.locPort(b)			# kicker ?	(locPort == first)
       
   137 	sete	N.kicker(b)
       
   138 1:	add	Cn.nodes(c), a
       
   139 	dec	a
       
   140 	mov	a, N.last(b)			# save port# of last node (last = first + nodes -1)
       
   141 	mov	Cn.nodes(c), a
       
   142 	mov	a, N.nodes(b)			# save num. of nodes in constellation
       
   143 	mov	Cn.div(c), a
       
   144 	mov	a, N.div(b)			# save divisor for random choice (MAX_INT / nodes)
       
   145 	mov	Cn.topo(c), a
       
   146 	mov	a, N.topo(b)
       
   147 	mov	Cn.forwP(c), a
       
   148 	mov	a, N.forwP(b)			# save -->shared "forward" indicator
       
   149 	movl	$0, N.closing(b)		# unset closing indicator
       
   150 # allocate and initialize server side and client side sockets
       
   151 	mov	$SocketInfoL, a
       
   152 	mull	N.nodes(b)			# SocketInfo array len
       
   153 	mov	a, N.sockArrLen(b)		# save array len
       
   154 	push	a
       
   155 	call	malloc
       
   156 	cmp	$0, a
       
   157 	jnl	0f
       
   158 	SYSERR	"malloc"
       
   159 0:	mov	thisP(bp), b			# -->this Node
       
   160 	mov	a, N.srvSideP(b)		# save -->array of server side sockets
       
   161 	pushl	N.sockArrLen(b)
       
   162 	call	malloc
       
   163 	cmp	$0, a
       
   164 	jnl	0f
       
   165 	SYSERR	"malloc"
       
   166 0:	mov	thisP(bp), b			# -->this Node
       
   167 	mov	a, N.cliSideP(b)		# save -->array of client side sockets
       
   168 # initialize allocated socket infos
       
   169 	xor	c, c				# offset
       
   170 0:	mov	N.srvSideP(b), a		# -->server side SocketInfo array
       
   171 #	movl	$So.labelV, So.label(a, c)	# indicate SocketInfo block
       
   172 	movl	$-1, So.sc(a, c)		# indicate server side socket is not in use
       
   173 	mov	N.cliSideP(b), a		# -->client side SocketInfo array
       
   174 #	movl	$So.labelV, So.label(a, c)	# indicate SocketInfo block
       
   175 	movl	$-1, So.sc(a, c)		# indicate client side socket is not in use
       
   176 	lea	SocketInfoL(c), c		# incr by SocketInfo len
       
   177 	cmp	c, N.sockArrLen(b)
       
   178 	ja	0b				# iterate
       
   179 
       
   180 	cmpl	$0, N.ssl(b)			# node's ssl switch
       
   181 	jz	N.initR				# no SSL
       
   182 # prepare SSL context
       
   183 #	call	SSL_load_error_strings
       
   184 #	call	SSL_library_init
       
   185 	call	OPENSSL_init_ssl
       
   186 	LOG	4, "setting SSL contex...", 0
       
   187 	call	TLS_method
       
   188 	push	a
       
   189 	call	SSL_CTX_new
       
   190 	mov	thisP(bp), b			# -->this Node
       
   191 	mov	a, N.ctxP(b)			# save -->new SSL context
       
   192 	test	a, a
       
   193 	jnz	0f
       
   194 	SSLERR	"new SSL CTX"
       
   195 # set SSL mode
       
   196 0:	pushl	$0
       
   197 	pushl	$4				# SSL_MODE_AUTO_RETRY
       
   198 	pushl	$33				# SSL_CTRL_MODE
       
   199 	pushl	N.ctxP(b)			# -->SSL context
       
   200 	call	SSL_CTX_ctrl
       
   201 	movl	$0, 8(sp)			# no callback
       
   202 	movl	$2, 4(sp)			# mode = SSL_VERIFY_FAIL_IF_NO_PEER_CERT
       
   203 	call	SSL_CTX_set_verify		# set peer certificate verification parameters
       
   204 # set X509 key file name
       
   205 	mov	thisP(bp), b			# -->this Node
       
   206 	pushl	N.locPort(b)			# local TCP port#
       
   207 	mov	C.csP, c
       
   208 	pushl	C.cePathP(c)			# -->name of SSL path
       
   209 	pushl	$0f				# -->format
       
   210 	pushl	$strL				# buf len
       
   211 	lea	str(bp), a
       
   212 	push	a				# -->string buf
       
   213 	call	snprintf
       
   214 	jmp	1f
       
   215 0:	.asciz	"%skeys/%u.key"
       
   216 1:
       
   217 	pushl	$1				# SSL_FILETYPE_PEM
       
   218 	lea	str(bp), a			# filename string
       
   219 	push	a
       
   220 	LOG	5, "SSL private key used: %s", 1
       
   221 	mov	thisP(bp), b			# -->this Node inst
       
   222 	pushl	N.ctxP(b)			# -->SSL context
       
   223 	call	SSL_CTX_use_PrivateKey_file
       
   224 	cmp	$1, a
       
   225 	je	0f
       
   226 	SSLERR	"hh's key file"
       
   227 # set X509 cert file name
       
   228 0:	mov	thisP(bp), b			# -->this Node
       
   229 	pushl	N.locPort(b)			# local TCP port #
       
   230 	mov	C.csP, c
       
   231 	pushl	C.cePathP(c)			# -->name of SSL path
       
   232 	pushl	$0f
       
   233 	pushl	$strL				# buf len
       
   234 	lea	str(bp), a			# string buf
       
   235 	push	a
       
   236 	call	snprintf
       
   237 	jmp	1f
       
   238 0:	.asciz	"%scerts/%u.pem"
       
   239 1:	mov	thisP(bp), b			# -->this Node
       
   240 	LOG	5, "SSL certificate used: %s", 1
       
   241 	pushl	$1				# SSL_FILETYPE_PEM
       
   242 	lea	str(bp), a			# filename string
       
   243 	push	a
       
   244 	pushl	N.ctxP(b)			# -->SSL context
       
   245 	call	SSL_CTX_use_certificate_file
       
   246 	cmp	$1, a
       
   247 	je	0f
       
   248 	SSLERR	"hh's cert file"
       
   249 # set path to CA
       
   250 0:	mov	thisP(bp), b			# -->this Node
       
   251 	mov	C.csP, c
       
   252 	pushl	C.caPathP(c)			# -->name of SSL path
       
   253 	pushl	$0f				# -->CApath
       
   254 	LOG	5, "SSL: CA path: %s", 1
       
   255 	pushl	$0				# -->CAfile not used
       
   256 	pushl	N.ctxP(b)			# -->SSL context
       
   257 	call	SSL_CTX_load_verify_locations	# set default locations for trusted CA certificates
       
   258 	cmp	$1, a
       
   259 	je	N.initR
       
   260 	SSLERR	"hh's thrusted certs path"
       
   261 0:	.asciz	"/home/local/etc/ssl/certs/"
       
   262 N.initR:
       
   263 	LOG	5, "initalized"
       
   264 	EPILOG
       
   265 #-----------------------------------------------
       
   266 #	K I C K   O F F
       
   267 #-----------------------------------------------
       
   268 	PROLOC
       
   269 	DL	thisP				# -->this Node
       
   270 	DL	deP				# -->Debug
       
   271 	DL	sci				# socket info rank
       
   272 	DL	digest, 24
       
   273 	EPILOC
       
   274 N.kickOff:
       
   275 	PROLOG
       
   276 	mov	b, thisP(bp)			# save -->this Node
       
   277 	lea	N.debug(b), a
       
   278 	mov	a, deP(bp)			# save local -->Debug
       
   279 # load payload data
       
   280 	movl	C.csP, c			# -->CS
       
   281 	push	C.txtP(c)			# -->initial payload text
       
   282 	push	C.ttl(c)			# initial TTL
       
   283 #	lea	N.data(b), a			# -->Data
       
   284 #	push	a
       
   285 	push	N.dataP(b)			# -->Data
       
   286 	call	Da.load				# load data container
       
   287 	call	N.nextNode
       
   288 	mov	a, N.next(b)			# save next node#
       
   289 	sub	N.first(b), a			# first - next = socketinfo rank
       
   290 	mov	a, sci(bp)			# save socket info rank
       
   291 	lea	digest(bp), a			# -->digest buf
       
   292 	push	a
       
   293 	push	N.dataP(b)			# -->Data
       
   294 	call	Da.digest24
       
   295 	call	Da.getDataLen
       
   296 	push	N.next(b)			# next node#
       
   297 	push	a				# data len
       
   298 	lea	digest(bp), a			# -->digest
       
   299 	push	a
       
   300 	LOG	2, "kicker: ready to initial send %s, len=%u to node %u"
       
   301 	push	N.next(b)
       
   302 	push	sci(bp)
       
   303 	call	N.conn				# connect to next node
       
   304 	push	sci(bp)
       
   305 	call	N.put				# send data to next node
       
   306 	EPILOG
       
   307 #-----------------------------------------------
       
   308 #	M A I N   L O O P :   I T E R A T E   O N   S O C K E T   I / O
       
   309 #-----------------------------------------------
       
   310 	PROLOC
       
   311 	DL	thisP				# -->this Node
       
   312 	DL	deP				# -->Debug
       
   313 	EPILOC
       
   314 N.mainLoop:
       
   315 	PROLOG
       
   316 	mov	b, thisP(bp)			# save -->this Node
       
   317 	lea	N.debug(b), a
       
   318 	mov	a, deP(bp)			# save local -->Debug
       
   319 # prepare
       
   320 	LOG	5, "preparing for I/O select..."
       
   321 	call	N.clearSocketMasks		# clear socket masks for select and zero nfds
       
   322 	call	N.maskSsc			# mask ssc for select
       
   323 # iterate while there are some sockets masked for select (nfds > 0)
       
   324 0:	cmp	$0, N.nfds(b)			# any I/O in progress ?
       
   325 	jz	0f				# no, end operations of node
       
   326 	call	N.selectSocketIo		# select on server side sockets and forward data
       
   327 	call	N.clearSocketMasks		# clear socket masks for select and zero nfds
       
   328 	call	N.maskSsc			# mask ssc for select
       
   329 	call	N.maskSrvSockets		# mask all connected server side sockets for select
       
   330 	jmp	0b
       
   331 0:	EPILOG
       
   332 #-----------------------------------------------
       
   333 #	S E L E C T   S O C K E T   I / O
       
   334 #-----------------------------------------------
       
   335 # select on masked sockets
       
   336 # upon return from select
       
   337 #	accept connections to ssc
       
   338 #	forward data from posted sockets
       
   339 #-----------------------------------------------
       
   340 	PROLOC
       
   341 	DL	thisP				# -->this Node
       
   342 	DL	deP				# -->Debug
       
   343 	EPILOC
       
   344 N.selectSocketIo:
       
   345 	PROLOG
       
   346 	mov	b, thisP(bp)			# save -->this Node
       
   347 	lea	N.debug(b), a
       
   348 	mov	a, deP(bp)			# save local -->Debug
       
   349 
       
   350 	push	N.nfds(b)
       
   351 	lea	N.rs(b), a
       
   352 	push	(a)
       
   353 	push	4(a)
       
   354 	push	N.ssc(b)
       
   355 	LOG	5, "select ssc=%u, mask=%08x %08x, nfds=%u"
       
   356 	lea	N.t(b), a			# -->timeval
       
   357 	movl	$1, Ti.secs(a)
       
   358 	movl	$0, Ti.usecs(a)
       
   359 	push	a
       
   360 	lea	N.es(b), a
       
   361 	push	a				# -->es (exceptional mask is not used yet)
       
   362 	pushl	$0
       
   363 	lea	N.rs(b), a			# -->rs
       
   364 	push	a
       
   365 	push	N.nfds(b)
       
   366 	SYS	select
       
   367 	lea	N.rs(b), a
       
   368 	push	(a)
       
   369 	push	4(a)
       
   370 	LOG	5, "return from select, mask of posted=%08x %08x"
       
   371 # check ssc for incomming connect request, accept it and forward data
       
   372 	lea	N.rs(b), a			# -->rs select mask
       
   373 	push	a
       
   374 	pushl	N.ssc(b)
       
   375 	call	fd_isset
       
   376 	test	a, a				# ssc I/O ?
       
   377 	jz	N.checkAndForw			# no, check other sockets
       
   378 # prepare for accept; find free srv socket info block for accept
       
   379 	mov	N.srvSideP(b), a		# -->srv socket info array
       
   380 	xor	c, c				# offet in socket info array
       
   381 	xor	d, d				# socket info rank
       
   382 0:	cmp	$-1, So.sc(a, c)		# socket allocated ?
       
   383 	je	0f				# no, free socket found
       
   384 	inc	d
       
   385 	lea	SocketInfoL(c), c		# inc offset into array
       
   386 	cmp	c, N.sockArrLen(b)
       
   387 	ja	0b				# iterate on sockets
       
   388 	ERR	"can't accept, all sockets in use"
       
   389 # free socket found, accept connection on it and forward data
       
   390 0:	push	d
       
   391 	LOG	4, "slot for accept=%d"
       
   392 	call	N.acc
       
   393 	call	N.forw
       
   394 # check all server side sockets for pending I/O and call forward on them
       
   395 N.checkAndForw:
       
   396 	xor	c, c				# offet into socket info array
       
   397 	lea	N.rs(b), a			# -->rs select mask
       
   398 	push	a
       
   399 	lea	-4(sp), sp			# adjust stacker for iteration
       
   400 	xor	c, c				# zero offset
       
   401 	xor	d, d				# set counter
       
   402 # iterate through server side sockets and forward from posted sockets
       
   403 0:	mov	N.srvSideP(b), a		# -->srv socket info array
       
   404 	cmp	$-1, So.sc(a, c)		# socket connected ?
       
   405 	je	1f				# no, iterate
       
   406 	mov	So.sc(a, c), a
       
   407 	mov	a, (sp)				# stack socket#
       
   408 #	LOG	0, "checking port %u"
       
   409 	call	fd_isset			# socket I/O ?
       
   410 	test	a, a
       
   411 	jz	1f				# no, iterate
       
   412 	mov	N.srvSideP(b), a
       
   413 	mov	So.sc(a, c), a
       
   414 	mov	d, (sp)				# stack socket rank
       
   415 #	LOG	0, "port posted, rank=%u"
       
   416 	call	N.forw				# forward data
       
   417 1:	inc	d
       
   418 	lea	SocketInfoL(c), c		# inc offset into array
       
   419 	cmp	c, N.sockArrLen(b)
       
   420 	ja	0b				# iterate on srv side sockets
       
   421 	EPILOG
       
   422 #-----------------------------------------------
       
   423 #	M A S K   C O N N E C T E D   S O C K E T S   F O R   S E L E C T
       
   424 #-----------------------------------------------
       
   425 # mask all connected server side socketS for next select
       
   426 	PROLOC
       
   427 	DL	thisP				# -->this Node
       
   428 	EPILOC
       
   429 N.maskSrvSockets:
       
   430 	PROLOG
       
   431 	mov	b, thisP(bp)			# save -->this Node
       
   432 
       
   433 	lea	N.rs(b), a			# -->rs select mask
       
   434 	push	a
       
   435 	lea	-4(sp), sp			# adjust stacker for iteration
       
   436 	xor	c, c				# zero offet
       
   437 0:	mov	N.srvSideP(b), a		# -->srv socket info array
       
   438 	cmp	$-1, So.sc(a, c)		# socket connected ?
       
   439 	je	1f				# no, iterate
       
   440 	mov	So.sc(a, c), a
       
   441 	mov	a, (sp)				# stack socket#
       
   442 	call	N.maskSocket			# mask socket for select
       
   443 1:	lea	SocketInfoL(c), c		# inc offset into array
       
   444 	cmp	c, N.sockArrLen(b)
       
   445 	ja	0b				# iterate on srv side sockets
       
   446 	EPILOG
       
   447 #-----------------------------------------------
       
   448 #	M A S K   S S C   F O R   S E L E C T
       
   449 #-----------------------------------------------
       
   450 # mask ssc for select until forward is disabled
       
   451 	PROLOC
       
   452 	DL	thisP				# -->this Node
       
   453 	EPILOC
       
   454 N.maskSsc:
       
   455 	PROLOG
       
   456 	mov	b, thisP(bp)			# save -->this Node
       
   457 
       
   458 	mov	N.forwP(b), a
       
   459 	cmp	$1, (a)				# forwarding enabled ?
       
   460 	jne	0f				# no, return
       
   461 	push	N.ssc(b)
       
   462 	call	N.maskSocket
       
   463 0:	EPILOG
       
   464 #-----------------------------------------------
       
   465 #	C L E A R   S O C K E T   M A S K S
       
   466 #-----------------------------------------------
       
   467 	PROLOC
       
   468 	DL	thisP				# -->this Node
       
   469 	EPILOC
       
   470 N.clearSocketMasks:
       
   471 	PROLOG
       
   472 	mov	b, thisP(bp)			# save -->this Node
       
   473 
       
   474 	movl	$0, N.nfds(b)			# zero nfds
       
   475 	lea	N.rs(b), a			# zero rs select mask
       
   476 	push	a
       
   477 	call	fd_zero
       
   478 	lea	N.es(b), a			# zero es select masks
       
   479 	push	a
       
   480 	call	fd_zero
       
   481 	EPILOG
       
   482 #-----------------------------------------------
       
   483 #	M A S K   S O C K E T   F O R   S E L E C T
       
   484 #-----------------------------------------------
       
   485 	ARGS
       
   486 	DS	sc				# socket#
       
   487 	PROLOC
       
   488 	DL	thisP				# -->this Node
       
   489 	EPILOC
       
   490 N.maskSocket:
       
   491 	PROLOG
       
   492 	mov	b, thisP(bp)			# save -->this Node
       
   493 
       
   494 	lea	N.rs(b), a			# -->rs select mask
       
   495 	push	a
       
   496 	pushl	sc(bp)
       
   497 	call	fd_set
       
   498 	mov	sc(bp), a			# socket#
       
   499 	cmp	a, N.nfds(b)			# nfds > sc ?
       
   500 	jg	0f				# yes
       
   501 	inc	a
       
   502 	mov	a, N.nfds(b)			# nfds = sc + 1
       
   503 0:	EPILOG
       
   504 #-----------------------------------------------
       
   505 #	F D   S E T   O P E R A T I N O S
       
   506 #-----------------------------------------------
       
   507 	PROLOC					# local data frame def. is used by 4 following subrs
       
   508 	DL	thisP				# -->this Node
       
   509 	dL	deP
       
   510 	EPILOC
       
   511 fd_zero:
       
   512 # zero FD mask
       
   513 	ARGS
       
   514 	DS	fdsetP				# -->FD mask
       
   515 	PROLOG
       
   516 	mov	fdsetP(bp), a
       
   517 	xor	c, c
       
   518 0:	movl	$0, (a, c, 4)
       
   519 	inc	c
       
   520 	cmp	$32, c				# size of FD mask is 32 int (1024 bits)
       
   521 	jl	0b
       
   522 	EPILOG
       
   523 fd_set:
       
   524 # mask socket in FD mask
       
   525 	ARGS
       
   526 	DS	sc
       
   527 	DS	fdsetP				# -->FD mask
       
   528 	PROLOG
       
   529 	movl	sc(bp), a			# sc
       
   530 	call	fd_mask				# a: integer offset, d: "1" bit in position according to sc
       
   531 	mov	fdsetP(bp), c			# -->select mask
       
   532 	or	d, (c, a)			# set sc mask
       
   533 	EPILOG
       
   534 fd_clear:
       
   535 # clear socket from FD mask
       
   536 	ARGS
       
   537 	DS	sc
       
   538 	DS	fdsetP				# -->FD mask
       
   539 	PROLOG
       
   540 	movl	sc(bp), a			# sc
       
   541 	call	fd_mask				# a: integer offset, d: "1" bit in position according to sc
       
   542 	mov	fdsetP(bp), c			# -->select mask
       
   543 	not	d
       
   544 	and	d, (c, a)			# clear sc mask
       
   545 	EPILOG
       
   546 fd_isset:
       
   547 # test socket bit status in FD mask
       
   548 	ARGS
       
   549 	DS	sc
       
   550 	DS	fdsetP				# -->FD mask
       
   551 	PROLOG
       
   552 	movl	sc(bp), a			# sc
       
   553 	call	fd_mask				# a: integer offset, d: "1" bit in position according to sc
       
   554 	mov	fdsetP(bp), c			# -->select mask
       
   555 	and	(c, a), d			# sc selected ?
       
   556 	mov	d, a
       
   557 #	mov	$0, a
       
   558 #	jz	0f				# not selected
       
   559 #	mov	$1, a
       
   560 0:	EPILOG_R
       
   561 fd_mask:					# a: sc
       
   562 # adjust offsets into FD mask
       
   563 	xor	d, d
       
   564 	movl	$32, c
       
   565 	divl	c				# a: mask integer rank, c: bit offset
       
   566 	shll	$2, a				# a: mask integer offset
       
   567 	mov	d, c
       
   568 	mov	$1, d
       
   569 	shl	%cl, d				# d: "1" bit in position according to sc
       
   570 	ret					# a: offset of mask integer
       
   571 #-----------------------------------------------
       
   572 #	F O R W A R D   D A T A   T O   O T H E R   N O D E
       
   573 #-----------------------------------------------
       
   574 	ARGS
       
   575 	DS	sci				# SocketInfo rank
       
   576 	PROLOC
       
   577 	DL	thisP				# -->this Node
       
   578 	DL	deP				# -->Debug inst
       
   579 	DL	digest, 24
       
   580 	EPILOC
       
   581 #-----------------------------------------------
       
   582 N.forw:
       
   583 	PROLOG
       
   584 	mov	b, thisP(bp)			# save -->this Node
       
   585 	lea	N.debug(b), a
       
   586 	mov	a, deP(bp)			# save local -->Debug
       
   587 
       
   588 	push	sci(bp)				# socket info rank
       
   589 	call	N.get
       
   590 	test	a, a				# data read ?
       
   591 	jz	N.forwCloseSock			# no, EOF, close this socket and start closing clients
       
   592 # kicker checks TTL
       
   593 	cmp	$1, N.kicker(b)			# kicker ?
       
   594 	jne	1f				# no, continue forwarding
       
   595 
       
   596 	lea	-4(sp), sp			# adjust stacker
       
   597 	lea	digest(bp), a
       
   598 	push	a				# -->digest buf
       
   599 	push	N.dataP(b)			# -->Data
       
   600 	call	Da.ttl
       
   601 	mov	a, 8(sp)			# TTL from data header
       
   602 	call	Da.digest24
       
   603 	mov	a, 4(sp)			# -->text digest
       
   604 	call	Da.getPort
       
   605 	mov	a, (sp)				# remote listen port from data header
       
   606 	LOG	5, "received from node %u: %s, ttl=%d"
       
   607 	push	N.dataP(b)			# -->Data
       
   608 	call	Da.dttl				# decrement TTL in data
       
   609 	test	a, a				# TTl > 0 ?
       
   610 	jz	N.forwKickerStop		# no, disable forwarding in constellation
       
   611 # forward data
       
   612 1:	call	N.nextNode			# calculate next node
       
   613 	mov	a, N.next(b)
       
   614 	push	a
       
   615 	LOG	4, "next node %u"
       
   616 	sub	N.first(b), a			# socket info rank (next - first)
       
   617 	mov	a, sci(bp)			# save
       
   618 # connect if not connected yet
       
   619 	movl	$SocketInfoL, d
       
   620 	mul	d				# a: offset into socket info array
       
   621 	mov	N.cliSideP(b), c		# -->client side socket info array
       
   622 	cmp	$-1, So.sc(c, a) 		# connected ?
       
   623 	jne	0f				# yes
       
   624 	push	N.next(b)
       
   625 	push	sci(bp)
       
   626 	call	N.conn
       
   627 0:
       
   628 	lea	-4(sp), sp
       
   629 	push	N.dataP(b)			# -->Data
       
   630 	call	Da.ttl
       
   631 	mov	a, 4(sp)			# ttl
       
   632 	call	Da.getDataLen
       
   633 	mov	a, (sp)				# container len
       
   634 	push	N.next(b)			# next node#
       
   635 	LOG	5, "forwarding to %d, len=%d, ttl=%d --->"
       
   636 # pacing
       
   637 	mov	C.csP, c			# -->CS
       
   638 	cmp	$0, C.pacing(c)			# pacing active ?
       
   639 	je	0f				# no
       
   640 	pushl	$0
       
   641 	lea	C.pace.tv_sec(c), a
       
   642 	push	a
       
   643 	SYS	nanosleep			# pace
       
   644 0:	push	sci(bp)
       
   645 	call	N.put
       
   646 	LOG	4, "leaving forward"
       
   647 	jmp	N.forwR				# exit forwarding
       
   648 N.forwKickerStop:				# ttl = 0
       
   649 	lea	digest(bp), a
       
   650 	push	a				# -->digest buf
       
   651 	push	N.dataP(b)			# -->Data
       
   652 	call	Da.digest24
       
   653 	push	a
       
   654 	LOG	1, "received after finally passing all: %s", 1
       
   655 	mov	N.forwP(b), a			# -->shared forw indicator
       
   656 	movl	$0, (a)				# disable forwarding for all nodes in constellation
       
   657 	jmp	N.forwCloseCli
       
   658 N.forwCloseSock:
       
   659 	pushl	deP(bp)
       
   660 	pushl	$1				# indicate "server side"
       
   661 	push	sci(bp)				# socket info rank
       
   662 	call	N.closeSocket			# close this server side socket
       
   663 N.forwCloseCli:
       
   664 	call	N.closeClients			# launch client side closing thread
       
   665 	LOG	4, "leaving forward, closing"
       
   666 N.forwR:
       
   667 	EPILOG
       
   668 #-----------------------------------------------
       
   669 #	D E T E R M I N E   N E X T   N O D E
       
   670 #-----------------------------------------------
       
   671 	PROLOC
       
   672 	DL	thisP				# -->this Node
       
   673 	EPILOC
       
   674 N.nextNode:
       
   675 	PROLOG
       
   676 	mov	b, thisP(bp)			# save -->this Node
       
   677 
       
   678 	cmp	$Cn.ring, N.topo(b)		# ring ?
       
   679 	jne	0f				# no
       
   680 # ring
       
   681 	mov	N.locPort(b), a
       
   682 	inc	a				# next = locPort + 1
       
   683 	cmp	a, N.last(b)			# next > last ?
       
   684 	jnl	N.nextNodeR
       
   685 	mov	N.first(b), a
       
   686 	jmp	N.nextNodeR
       
   687 # mash
       
   688 0:	call	random
       
   689 	xor     d, d
       
   690 	mov	thisP(bp), b
       
   691         divl    N.div(b)			# 0 <= random < nodes
       
   692         add	N.first(b), a			# first + random
       
   693         cmp	a, N.locPort(b)
       
   694         je	0b				# iterate until other then local node is selected
       
   695 N.nextNodeR:
       
   696 	push	a
       
   697 	EPILOG_R
       
   698 
       
   699 #-----------------------------------------------
       
   700 #	B I N D   T O   L O C A L   T C P   P O R T
       
   701 #-----------------------------------------------
       
   702 # returns
       
   703 #	nothing
       
   704 	PROLOC
       
   705 	DL	thisP				# -->this Node
       
   706 	DL	deP				# -->Debug
       
   707 	DL	i
       
   708 	DL	aiP				# -->IP addrinfo
       
   709 	strL = 64
       
   710 	DL	str, strL			# string buf
       
   711 	EPILOC
       
   712 #-----------------------------------------------
       
   713 	.global N.bind
       
   714 N.bind:
       
   715 	PROLOG
       
   716 	mov	b, thisP(bp)			# save -->this Node
       
   717 	lea	N.debug(b), a
       
   718 	mov	a, deP(bp)			# save local -->Debug
       
   719 	LOG	4, "binding...", 0
       
   720 # prepare IP addr
       
   721 	pushl	$AddrInfoL
       
   722 	call	malloc				# alloc addrinfo for hints
       
   723 	mov	a, aiP(bp)
       
   724 	pushl	$AddrInfoL
       
   725 	pushl	$0
       
   726 	push	a
       
   727 	call	memset				# clear hints
       
   728 
       
   729 	movl	$2, ai_family(a)		# AF_INET
       
   730 	movl	$1, ai_flags(a)			# AI_PASSIVE for bind
       
   731 	movl	$0, ai_protocol(a)		# any protocol
       
   732 	movl	$1, ai_socktype(a)		# SOCK_STREAM, blocking type
       
   733 
       
   734 	mov	thisP(bp), b			# -->this Node
       
   735 	pushl	N.locPort(b)			# local port #
       
   736 	push	$0f
       
   737 	lea	str(bp), a
       
   738 	push	a				# -->str buff
       
   739 	call	sprintf
       
   740 	jmp	1f
       
   741 0:	.ascii	"%d\0"
       
   742 1:
       
   743 	lea	aiP(bp), a
       
   744 	push	a				# -->-->addrinfo for new addrinfo
       
   745 	pushl	aiP(bp)				# -->addrinfo hints
       
   746 	lea	str(bp), a
       
   747 	push	a				# -->loc port # string
       
   748 	pushl	$0f
       
   749 	call	getaddrinfo
       
   750 	jmp	1f
       
   751 0:	.ascii	"localhost\0"
       
   752 # check IP addr
       
   753 1:	cmp	$0, a				# getaddrinfo OK ?
       
   754 	jz	0f				# yes
       
   755 	push	a
       
   756 	call	gai_strerror
       
   757 	push	a
       
   758 	LOG	0, "getaddrinfo error: %s, ABEND", 1
       
   759 	push	$1
       
   760 	call	exit
       
   761 # log assigned IP addr
       
   762 0:	pushl	deP(bp)
       
   763 	mov	aiP(bp), a			# -->addrinfo
       
   764 	pushl	ai_addrP(a)			# -->sockaddr
       
   765 	lea	str(bp), a
       
   766 	push	a				# -->string buf
       
   767 	call	gai
       
   768 
       
   769 	lea	str(bp), a
       
   770 	push	a
       
   771 	LOG	5, "getaddrinfo OK, %s", 1
       
   772 # allocate socket
       
   773 	mov	aiP(bp), a
       
   774 	pushl	ai_protocol(a)
       
   775 	pushl	ai_socktype(a)
       
   776 	pushl	ai_family(a)
       
   777 	SYS	socket
       
   778 	mov	a, N.ssc(b)			# save ssc
       
   779 # set socket option SO_REUSEADDR
       
   780 	pushl	$4				# integer width
       
   781 	lea		9f, a			# value 1
       
   782 	push	a
       
   783 	pushl	$2				# SO_REUSEADDR
       
   784 	pushl	$1				# SOL_SOCKET
       
   785 	push	N.ssc(b)			# ssc
       
   786 	SYS setsockopt
       
   787 	jmp		8f
       
   788 9:	.long	1
       
   789 8:
       
   790 # bind
       
   791 	mov	aiP(bp), a
       
   792 	pushl	ai_addrlen(a)
       
   793 	pushl	ai_addrP(a)
       
   794 	push	N.ssc(b)			# ssc
       
   795 	SYS	bind
       
   796 # listen
       
   797 	pushl	$1				# pend conns queue len
       
   798 	pushl	N.ssc(b)			# ssc
       
   799 	SYS	listen
       
   800 	pushl	N.locPort(b)
       
   801 	LOG	2, "bound to %d", 1
       
   802 N.bindR:
       
   803 	EPILOG
       
   804 #-----------------------------------------------
       
   805 #	C O N N E C T   T O   R E M O T E   N O D E
       
   806 #-----------------------------------------------
       
   807 # args
       
   808 	ac = 40
       
   809 	DS	i				# socket rank
       
   810 	DS	remPort				# TCP port# on remote site
       
   811 # returns
       
   812 #	nothing
       
   813 # local vars
       
   814 	ac = 0
       
   815 	DL	debug, DebugL			# Debug inst
       
   816 	DL	deP				# -->Debug inst
       
   817 	DL	retry				# retry counter
       
   818 	DL	ai, AddrInfoL			# IP addrinfo
       
   819 	DL	aiP				# -->IP addrinfo
       
   820 	DL	str, 64				# string buf
       
   821 	DL	currSockP			# -->SocketInfo save area
       
   822 	locL = ac
       
   823 #-----------------------------------------------
       
   824 	.global N.conn
       
   825 N.conn:
       
   826 	PROLOG
       
   827 	mov	b, thisP(bp)			# save -->this Node
       
   828 	lea	debug(bp), a			# -->own local debug block
       
   829 	mov	a, deP(bp)			# save -->local Debug
       
   830 	pushl	remPort(bp)			# remote port
       
   831 	lea	N.debug(b), d			# -->node's Debug
       
   832 	lea	D.id(d), a			# -->node's debug ID
       
   833 	push	a
       
   834 	DEBID	"%s to %u", 2			# set local debug ID
       
   835 	LOG	3, "connecting...", 0
       
   836 
       
   837 	mov	N.cliSideP(b), c		# -->SocketInfo array
       
   838 	mov	$SocketInfoL, a
       
   839 	mull	i(bp)				# SocketInfo offset
       
   840 	lea	(c, a), c			# -->curr SocketInfo
       
   841 	mov	c, currSockP(bp)		# save -->curr SocketInfo
       
   842 	mov	remPort(bp), a
       
   843 	mov	a, So.remPort(c)		# put remote port # into curr SocketInfo
       
   844 # prepare IP addrinfo hints
       
   845 	pushl	$AddrInfoL			# IP addrinfo length
       
   846 	pushl	$0
       
   847 	lea	ai(bp), a
       
   848 	mov	a, aiP(bp)			# -->IP addrinfo
       
   849 	push	a
       
   850 	call	memset				# clear addrinfo
       
   851 	movl	$2, ai_family(a)		# AF_INET
       
   852 	movl	$0, ai_flags(a)
       
   853 	movl	$0, ai_protocol(a)		# any protocol
       
   854 	movl	$1, ai_socktype(a)		# SOCK_STREAM
       
   855 # set up port # string
       
   856 	mov	currSockP(bp), a		# -->curr socket info
       
   857 	pushl	So.remPort(a)			# remote port#
       
   858 	pushl	$0f
       
   859 	lea	str(bp), a
       
   860 	push	a				# -->port# string
       
   861 	call	sprintf
       
   862 	jmp	1f
       
   863 0:	.ascii	"%u\0"
       
   864 # get IP addrinfo block chain
       
   865 1:	lea	aiP(bp), a			# -->-->IP addrinfo
       
   866 	push	a
       
   867 	pushl	aiP(bp)				# -->IP addrinfo hints
       
   868 	lea	str(bp), a			# -->remote port # string
       
   869 	push	a
       
   870 	pushl	$0f
       
   871 	call	getaddrinfo
       
   872 	jmp	1f
       
   873 0:	.ascii	"localhost\0"
       
   874 # check IP addr
       
   875 1:	cmp	$0, a				# getaddrinfo OK ?
       
   876 	jz	0f				# yes
       
   877 	push	a
       
   878 	call	gai_strerror
       
   879 	push	a
       
   880 	LOG	0, "getaddrinfo error: %s, ABEND", 1
       
   881 	push	$1
       
   882 	call	exit				# ABEND
       
   883 # log assigned IP addr
       
   884 0:	pushl	deP(bp)				# -->Debug inst
       
   885 	mov	aiP(bp), a			# -->IP addrinfo
       
   886 	pushl	ai_addrP(a)			# -->sockaddr
       
   887 	lea	str(bp), a
       
   888 	push	a				# -->string buf
       
   889 	call	gai
       
   890 	LOG	5, "getaddrinfo OK, %s", 1
       
   891 # allocate comm socket
       
   892 	mov	aiP(bp), a			# -->IP addrinfo
       
   893 	pushl	ai_protocol(a)
       
   894 	pushl	ai_socktype(a)
       
   895 	pushl	ai_family(a)
       
   896 #	call	socket				# allocate comm socket
       
   897 #	cmp	$0, a
       
   898 #	jg	0f
       
   899 #	SYSERR	"socket alloc"
       
   900 #0:
       
   901 	SYS	socket
       
   902 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   903 	mov	a, So.sc(c)			# put new socket # into SocketInfo
       
   904 # connect to remote partner server side
       
   905 	mov	C.csP, a
       
   906 	mov	C.connTh(a), a			# conn retry threshold
       
   907 	mov	a, retry(bp)			# initilize retry counter
       
   908 	mov	aiP(bp), a			# -->IP addrinfo
       
   909 	pushl	ai_addrlen(a)
       
   910 	pushl	ai_addrP(a)
       
   911 	pushl	So.sc(c)			# socket #
       
   912 2:	call	connect
       
   913 	cmp	$0, a
       
   914 	jnl	0f				# connected
       
   915 	call    __errno_location                # get --> sys errno
       
   916 	cmp	$111, (a)			# ECONNREFUSED ?
       
   917 	je	1f				# yes, wait to retry
       
   918 	SYSERR	"connect"			# no, ABEND
       
   919 1:	pushl	$22000				# 22 msecs
       
   920 	call	usleep
       
   921 	lea	4(sp), sp
       
   922 	sub	$1, retry(bp)
       
   923 	jnz	2b				# iterate
       
   924 # conn retry threshold reached
       
   925 	mov	C.csP, a
       
   926 	pushl	C.connTh(a)
       
   927 	LOG	0, "connection refused, threshold %d reached", 1
       
   928 	pushl	$1
       
   929 	call	exit				# ABEND
       
   930 0:
       
   931 # connected, account new connection
       
   932 	mov	C.csP, c			# -->CS
       
   933 	mov	C.shP(c), a			# -->shared mem
       
   934 	lea	S.counter_sem(a), a		# -->overall counter semaphore
       
   935 	push	a
       
   936 	SYS	sem_wait
       
   937 	mov	C.csP, c			# -->CS
       
   938 	mov	C.shP(c), a			# -->shared mem
       
   939 	incl	S.conns(a)			# incr conns counter
       
   940 	lea	S.counter_sem(a), a		# -->overall msg counter semaphore
       
   941 	push	a
       
   942 	SYS	sem_post
       
   943 # prepare SSL
       
   944 	cmp	$1, N.ssl(b)			# node's ssl switch
       
   945 	jne	N.connRet			# no SSL
       
   946 
       
   947 	LOG	5, "prepare for SSL"
       
   948 	pushl	N.ctxP(b)			# -->SSL context
       
   949 	call	SSL_new				# create a SSL structure
       
   950 
       
   951 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   952 	mov	a, So.sslP(c)			# put -->SSL struct into SocketInfo
       
   953 	test	a, a
       
   954 	jnz	0f
       
   955 	SSLERR	"new SSL"
       
   956 # connect on SSL
       
   957 0:	call	ERR_clear_error
       
   958 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   959 	pushl	So.sc(c)			# socket
       
   960 	pushl	So.sslP(c)			# -->SSL struct
       
   961 	call	SSL_set_fd			# connect the SSL object with a file descriptor
       
   962 	test	a, a
       
   963 	jnz	0f
       
   964 	SSLERR	"client SSL set fd"
       
   965 0:
       
   966 	LOG	5, "SSL fd set"
       
   967 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   968 	pushl	So.sslP(c)			# -->SSL struct
       
   969 	call	SSL_connect
       
   970 	test	a, a				# connected ?
       
   971 	jns	1f				# yes
       
   972 	push	a
       
   973 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   974 	pushl	So.sslP(c)			# -->SSL struct
       
   975 	call	SSL_get_error			# SSL_get_error(-->ssl, err)
       
   976 	cmp	$5, a				# SSL_ERROR_SYSCALL ?
       
   977 	jne	0f				# no, other SSL err
       
   978 	SYSERR	"SSL connect"
       
   979 0:	SSLERR	"SSL connect"
       
   980 1:
       
   981 	mov	C.csP, a
       
   982 	mov	C.connTh(a), a
       
   983 	sub	retry(bp), a			# # of retries = conn threshold - counter
       
   984 	push	a
       
   985 	mov	currSockP(bp), c		# -->curr SocketInfo
       
   986 	pushl	So.sc(c)			# socket#
       
   987 	LOG	2, "connected via sc=%d after %d retries", 2
       
   988 N.connRet:
       
   989 	EPILOG
       
   990 #-----------------------------------------------
       
   991 #	A C C E P T   C O N N E C T I O N
       
   992 #-----------------------------------------------
       
   993 	ARGS
       
   994 	DS	i				# socket rank
       
   995 # returns
       
   996 #	nothing
       
   997 # local vars
       
   998 	PROLOC
       
   999 	DL	thisP				# -->this Node
       
  1000 	DL	deP				# -->Debug inst
       
  1001 	DL	sa, SockAddrL			# sockaddr
       
  1002 	DL	str, 64				# string buf
       
  1003 	DL	currSockP			# -->curr SocketInfo save area
       
  1004 	EPILOC
       
  1005 #-----------------------------------------------
       
  1006 	.global N.acc
       
  1007 N.acc:
       
  1008 	PROLOG
       
  1009 	mov	b, thisP(bp)			# save -->this Node
       
  1010 	lea	N.debug(b), a
       
  1011 	mov	a, deP(bp)			# save local -->Debug
       
  1012 	LOG	4, "accepting..."
       
  1013 
       
  1014 	mov	N.srvSideP(b), c		# -->SocketInfo array
       
  1015 	mov	$SocketInfoL, a
       
  1016 	mull	i(bp)				# curr SocketInfo offset
       
  1017 	lea	(c, a), a			# -->curr SocketInfo
       
  1018 	mov	a, currSockP(bp)		# save -->curr SocketInfo
       
  1019 # accept
       
  1020 	pushl	$0
       
  1021 	pushl	$0
       
  1022 #	mov	thisP, b			# -->Node inst
       
  1023 	pushl	N.ssc(b)			# listen socket
       
  1024 #	call	accept
       
  1025 #	cmp	$0, a
       
  1026 #	jnl	0f
       
  1027 #	SYSERR	"accept"
       
  1028 #0:
       
  1029 	SYS	accept
       
  1030 	mov	currSockP(bp), c		# -->Node inst
       
  1031 	mov	a, So.sc(c)			# save comm socket of accepted connection
       
  1032 	pushl	$0f				# -->sa length
       
  1033 	lea	sa(bp), a			# -->sockaddr
       
  1034 	push	a
       
  1035 	pushl	So.sc(c)			# comm socket
       
  1036 	call	getpeername
       
  1037 	jmp	1f
       
  1038 0:	.int	SockAddrL
       
  1039 1:	pushl	deP(bp)
       
  1040 	lea	sa(bp), a			# -->sockaddr
       
  1041 	push	a
       
  1042 	lea	str(bp), a			# -->string buf
       
  1043 	push	a
       
  1044 	call	gai				# get string of addr/port
       
  1045 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1046 	pushl	So.sc(c)			# comm socket
       
  1047 	LOG	3, "peer: sc=%d, %s", 2
       
  1048 # prepare SSL
       
  1049 	mov	thisP(bp), b			# -->this Node
       
  1050 	cmp	$1, N.ssl(b)			# node's ssl switch
       
  1051 	jne	1f				# no SSL
       
  1052 
       
  1053 	pushl	N.ctxP(b)			# -->SSL context
       
  1054 	call	SSL_new				# create a SSL structure
       
  1055 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1056 	mov	a, So.sslP(c)			# put -->SSL struct into SocketInfo
       
  1057 	test	a, a
       
  1058 	jnz	0f
       
  1059 	SSLERR	"new SSL"
       
  1060 # accept on SSL
       
  1061 0:	call	ERR_clear_error
       
  1062 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1063 	pushl	So.sc(c)			# socket #
       
  1064 	pushl	So.sslP(c)			# -->SSL struct
       
  1065 	call	SSL_set_fd			# connect the SSL object with a file descriptor
       
  1066 	test	a, a
       
  1067 	jnz	0f
       
  1068 	SSLERR	"client SSL set fd"
       
  1069 0:
       
  1070 	LOG	5, "SSL fd set"
       
  1071 	call	SSL_accept
       
  1072 	test	a, a
       
  1073 	jns	1f
       
  1074 	mov	a, 4(sp)
       
  1075 	call	SSL_get_error			# SSL_get_error(-->ssl, err)
       
  1076 	cmp	$5, a				# SSL_ERROR_SYSCALL ?
       
  1077 	jne	0f				# no, other SSL err
       
  1078 	SYSERR	"SSL accept"
       
  1079 0:	SSLERR	"SSL accept"
       
  1080 1:
       
  1081 	LOG	2, "accepted"
       
  1082 	EPILOG
       
  1083 #-----------------------------------------------
       
  1084 #	R E A D   F R O M   C O M M   S O C K E T
       
  1085 #-----------------------------------------------
       
  1086 	ARGS
       
  1087 	DS	sci				# SocketInfo rank
       
  1088 # returns	length read
       
  1089 	PROLOC
       
  1090 	DL	thisP				# -->this Node
       
  1091 	DL	deP				# -->Debug inst
       
  1092 	DL	shP				# -->shared mem
       
  1093 	DL	currSockP			# -->curr SocketInfo
       
  1094 	DL	n				# len read
       
  1095 	DL	rest				# len to be read
       
  1096 	DL	buf				# read dest
       
  1097 	EPILOC
       
  1098 #-----------------------------------------------
       
  1099 	.global N.read
       
  1100 N.read:
       
  1101 	PROLOG
       
  1102 	mov	b, thisP(bp)			# save -->this Node
       
  1103 	lea	N.debug(b), a
       
  1104 	mov	a, deP(bp)			# save local -->Debug
       
  1105 
       
  1106 	mov	C.csP, a			# -->CS
       
  1107 	mov	C.shP(a), a			# -->shared mem
       
  1108 	mov	a, shP(bp)			# save -->shared mem
       
  1109 	push	N.dataP(b)
       
  1110 	call	Da.getDataLen
       
  1111 	mov	a, rest(bp)			# init len to be read
       
  1112 	call	Da.getContP
       
  1113 	mov	a, buf(bp)			# init read dest
       
  1114 	mov	N.srvSideP(b), c		# -->server side SocketInfo array
       
  1115 	mov	$SocketInfoL, a
       
  1116 	mull	sci(bp)				# curr SocketInfo offset
       
  1117 	lea	(c, a), c			# -->curr SocketInfo
       
  1118 	mov	c, currSockP(bp)		# save -->curr SocketInfo
       
  1119 
       
  1120 	push	So.sc(c)			# comm socket
       
  1121 	push	rest(bp)			# len to be read
       
  1122 	LOG	5, "ready to read len=%d from sc=%d..."
       
  1123 # iterate on reading until whole length is read
       
  1124 N.readIterate:
       
  1125 	cmp	$0, rest(bp)			# something to be read ?
       
  1126 	jng	N.readAcc			# no, end reading
       
  1127 	push	rest(bp)			# len to be read
       
  1128 	push	buf(bp)				# read dest
       
  1129 	mov	currSockP(bp), c		# curr SocketInfo
       
  1130 	cmp	$1, N.ssl(b)			# SSL ?
       
  1131 	jne	0f				# no
       
  1132 # read w/ SSL
       
  1133 	push	So.sslP(c)			# -->SSL struct
       
  1134 	SYS	SSL_read
       
  1135 	jmp	1f
       
  1136 # read w/o SSL
       
  1137 0:
       
  1138 	push	So.sc(c)			# socket #
       
  1139 	SYS	read
       
  1140 # adjust read controls
       
  1141 1:
       
  1142 	jz	N.readEof			# EOF read
       
  1143 	add	a, buf(bp)			# adjust -->read dest
       
  1144 	sub	a, rest(bp)			# decrement rest to read
       
  1145 	cmp	$0, rest(bp)			# everything read ?
       
  1146 	jng	0f
       
  1147 	push	a
       
  1148 	LOG	5, "partly read %d bytes"
       
  1149 0:	jmp	N.readIterate
       
  1150 # account data just read
       
  1151 N.readAcc:
       
  1152 	mov	shP(bp), a			# -->shared mem
       
  1153 	lea	S.counter_sem(a), a		# overall msg counter semaphore
       
  1154 	push	a
       
  1155 	SYS	sem_wait			# get semaphore
       
  1156 	mov	shP(bp), a
       
  1157 	incl	S.msgs(a)			# incr msgs counter
       
  1158 	lea	S.counter_sem(a), a		# overall msg counter semaphore
       
  1159 	push	a
       
  1160 	SYS	sem_post			# post semaphore
       
  1161 
       
  1162 	lea	-4(sp), sp			# adjust stacker
       
  1163 	push	N.dataP(b)			# -->Data
       
  1164 	call	Da.getPort
       
  1165 	mov	a, 4(sp)			# remote listen port
       
  1166 	call	Da.getDataLen
       
  1167 	mov	a, (sp)				# data length
       
  1168 	LOG	5, "%d read from node %u"
       
  1169 	mov	(sp), a				# return len read
       
  1170 	jmp	N.readRet
       
  1171 # EOF read, finish
       
  1172 N.readEof:
       
  1173 	LOG	4, "EOF read"
       
  1174 N.readRet:
       
  1175 	EPILOG_R
       
  1176 #-----------------------------------------------
       
  1177 #	W R I T E   T O   C O M M   S O C K E T
       
  1178 #-----------------------------------------------
       
  1179 	ARGS
       
  1180 	DS	sci				# SocketInfo rank
       
  1181 # returns	length written
       
  1182 	PROLOC
       
  1183 	DL	thisP				# -->this Node
       
  1184 	DL	deP				# -->Debug inst
       
  1185 	DL	currSockP			# -->curr SocketInfo
       
  1186 	DL	n				# len written
       
  1187 	DL	rest				# len to be written
       
  1188 	DL	buf				# write orig
       
  1189 	EPILOC
       
  1190 #-----------------------------------------------
       
  1191 	.global N.write
       
  1192 N.write:
       
  1193 	PROLOG
       
  1194 	mov	b, thisP(bp)			# save -->this Node
       
  1195 	lea	N.debug(b), a
       
  1196 	mov	a, deP(bp)			# save local -->Debug
       
  1197 # init control values
       
  1198 	mov	C.csP, a			# -->CS
       
  1199 	mov	C.shP(a), a			# -->shared mem
       
  1200 	mov	a, shP(bp)			# save -->shared mem
       
  1201 	push	N.dataP(b)			# -->Data
       
  1202 	call	Da.getDataLen
       
  1203 	mov	a, rest(bp)			# init len to be written
       
  1204 	call	Da.getContP
       
  1205 	mov	a, buf(bp)			# init write orig
       
  1206 	mov	N.cliSideP(b), c		# -->SocketInfo array
       
  1207 	mov	$SocketInfoL, a
       
  1208 	mull	sci(bp)				# curr SocketInfo offset
       
  1209 	lea	(c, a), c			# -->curr SocketInfo
       
  1210 	mov	c, currSockP(bp)		# save -->curr SocketInfo
       
  1211 
       
  1212 	push	So.sc(c)			# comm socket
       
  1213 	push	rest(bp)			# len to be written
       
  1214 	LOG	5, "ready to write len=%d to sc=%d..."
       
  1215 # iterate on writing until whole length is written
       
  1216 N.writeIterate:
       
  1217 	cmp	$0, rest(bp)			# something to be written ?
       
  1218 	jng	N.writeEnd			# no, end writing
       
  1219 	push	rest(bp)			# len to be written
       
  1220 	push	buf(bp)				# write orig
       
  1221 	cmp	$1, N.ssl(b)			# SSL ?
       
  1222 	jne	0f				# no
       
  1223 # SSL
       
  1224 	pushl	So.sslP(c)			# -->SSL struct
       
  1225 	SYS	SSL_write
       
  1226 	jmp	1f
       
  1227 # no SSL
       
  1228 0:
       
  1229 	pushl	So.sc(c)			# socket
       
  1230 	SYS	write
       
  1231 # adjust write controls
       
  1232 1:
       
  1233 	mov	a, n(bp)			# save len written
       
  1234 	add	a, buf(bp)			# adjust write orig
       
  1235 	sub	a, rest(bp)			# decrement rest to write
       
  1236 	cmp	$0, rest(bp)			# everything written ?
       
  1237 	jng	0f
       
  1238 	push	a
       
  1239 	LOG	5, "partly written %d bytes"
       
  1240 0:	jmp	N.writeIterate
       
  1241 # return datalen
       
  1242 N.writeEnd:
       
  1243 	mov	N.dataP(b), a
       
  1244 	mov	Da.datalen(a), a
       
  1245 	push	a
       
  1246 	LOG	5, "%d written", 1
       
  1247 	EPILOG_R
       
  1248 #-----------------------------------------------
       
  1249 #	G E T   D A T A   F R O M   C O M M   S O C K E T
       
  1250 #-----------------------------------------------
       
  1251 	ARGS
       
  1252 	DS	sci				# SocketInfo rank
       
  1253 # returns	boolean: 0 - EOF read, 1 - data read
       
  1254 	PROLOC
       
  1255 	DL	thisP				# -->this Node
       
  1256 	DL	deP
       
  1257 	EPILOC
       
  1258 #-----------------------------------------------
       
  1259 	.global N.get
       
  1260 N.get:
       
  1261 	PROLOG
       
  1262 	mov	b, thisP(bp)			# save -->this Node
       
  1263 	lea	N.debug(b), a
       
  1264 	mov	a, deP(bp)			# save local -->Debug
       
  1265 	push	sci(bp)				# SocketInfo rank
       
  1266 	LOG	5, "get data from socket, rank=%u"
       
  1267 	call	N.read
       
  1268 	test	a, a
       
  1269 	jz	0f
       
  1270 	mov	$1, a
       
  1271 0:	EPILOG_R
       
  1272 #-----------------------------------------------
       
  1273 #	P U T   D A T A   T O   C O M M   S O C K E T
       
  1274 #-----------------------------------------------
       
  1275 	ARGS
       
  1276 	DS	sci				# SocketInfo rank
       
  1277 # returns	boolean: 0 - nothing written, 1 - data written
       
  1278 	PROLOC
       
  1279 	DL	thisP				# -->this Node
       
  1280 	DL	deP
       
  1281 	EPILOC
       
  1282 #-----------------------------------------------
       
  1283 	.global N.put
       
  1284 N.put:
       
  1285 	PROLOG
       
  1286 	mov	b, thisP(bp)			# save -->this Node
       
  1287 	lea	N.debug(b), a
       
  1288 	mov	a, deP(bp)			# save local -->Debug
       
  1289 	LOG	5, "put data to socket"
       
  1290 
       
  1291 	mov	N.dataP(b), d			# -->Data
       
  1292 	mov	Da.contP(d), a			# -->container
       
  1293 	lea	Co.hdr(a), a			# -->header
       
  1294 	mov	N.locPort(b), c
       
  1295 	mov	c, H.lport(a)			# listen port to header
       
  1296 
       
  1297 	pushl	sci(bp)				# SocketInfo rank
       
  1298 	call	N.write
       
  1299 	test	a, a
       
  1300 	jz	0f
       
  1301 	mov	$1, a
       
  1302 0:	EPILOG_R
       
  1303 #-----------------------------------------------
       
  1304 #	C L O S E   C O N N E C T I O N   S O C K E T
       
  1305 #-----------------------------------------------
       
  1306 	ARGS
       
  1307 	DS	sci				# SocketInfo rank
       
  1308 	DS	server				# indicate server or client
       
  1309 	DS	deP				# -->Debug inst
       
  1310 # returns:#	nothing
       
  1311 	PROLOC
       
  1312 	DL	thisP				# -->this Node
       
  1313 	DL	currSockP			# -->curr SocketInfo
       
  1314 	DL	tagP
       
  1315 	DL	e
       
  1316 	EPILOC
       
  1317 N.srvSideTag:	.asciz	"server side"
       
  1318 N.cliSideTag:	.asciz	"client side"
       
  1319 #-----------------------------------------------
       
  1320 	.global N.closeSocket
       
  1321 N.closeSocket:
       
  1322 	PROLOG
       
  1323 	mov	b, thisP(bp)			# save -->this Node
       
  1324 	mov	N.srvSideP(b), c		# -->SocketInfo array
       
  1325 	movl	$N.srvSideTag, tagP(bp)
       
  1326 	cmp	$1, server(bp)			# server side ?
       
  1327 	je	0f
       
  1328 	mov	N.cliSideP(b), c		# client side
       
  1329 	movl	$N.cliSideTag, tagP(bp)
       
  1330 0:	mov	$SocketInfoL, a
       
  1331 	mull	sci(bp)				# curr SocketInfo offset
       
  1332 	lea	(c, a), c
       
  1333 	mov	c, currSockP(bp)		# save -->curr SocketInfo
       
  1334 	push	So.sc(c)			# socket to close
       
  1335 	push	tagP(bp)
       
  1336 	LOG	5, "closing %s sc=%u...", 2
       
  1337 
       
  1338 	cmp	$0, N.ssl(b)			# SSL ?
       
  1339 	je	2f				# no
       
  1340 # SSL shutdown
       
  1341 	pushl	So.sslP(c)			# -->SSL structure
       
  1342 	call 	SSL_shutdown
       
  1343 	cmp	$0, a
       
  1344 	jns	0f				# no err
       
  1345 	SSLERR	"SSL shutdown (1)"
       
  1346 0:	jnz	2f				# SSL shutdown finished
       
  1347 	LOG	5, "SSL shutdown rc=0, retry"
       
  1348 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1349 	pushl	So.sslP(c)			# -->SSL structure
       
  1350 	call 	SSL_shutdown
       
  1351 	cmp	$0, a
       
  1352 	jg	2f				# SSL shutdown finished
       
  1353 	push	a				# SSL err
       
  1354 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1355 	pushl	So.sslP(c)			# -->SSL structure
       
  1356 	call	SSL_get_error
       
  1357 	cmp	$5, a				# SSL_ERROR_SYSCALL ?
       
  1358 	jne	1f				# no, other SSL err
       
  1359 # syscall err
       
  1360 	call	ERR_get_error
       
  1361 	test	a, a				# SSL err ?
       
  1362 	jnz	2f				# yes, don't care
       
  1363 	call	__errno_location		# sys err ?
       
  1364 	test	a, a
       
  1365 	jz	2f				# no
       
  1366 	SYSERR	"SSL shutdown (2)"
       
  1367 # other SSL err, print SSL err queue
       
  1368 1:	SSLERR	"SSL shutdown (2)"
       
  1369 # close socket
       
  1370 2:	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1371 	pushl	So.sc(c)			# socket to close
       
  1372 #	call	close
       
  1373 #	test	a, a
       
  1374 #	jz	0f
       
  1375 #	SYSERR	"close"
       
  1376 #0:
       
  1377 	SYS	close
       
  1378 	push	tagP(bp)
       
  1379 	LOG	4, "%s sc=%u closed", 2
       
  1380 	mov	currSockP(bp), c		# -->curr SocketInfo
       
  1381 	movl	$-1, So.sc(c)			# indicate closed socket
       
  1382 	EPILOG
       
  1383 #-----------------------------------------------
       
  1384 #	C R E A T E   T H R E A D   T O   C L O S E   C L I E N T   S I D E S
       
  1385 #-----------------------------------------------
       
  1386 	ARGS
       
  1387 	PROLOC
       
  1388 	DL	thisP				# -->this Node
       
  1389 	DL	deP				# -->Debug inst
       
  1390 	DL	pt				# pthread_t (int)
       
  1391 	EPILOC
       
  1392 #-----------------------------------------------
       
  1393 N.closeClients:
       
  1394 	PROLOG
       
  1395 	mov	b, thisP(bp)			# save -->this Node
       
  1396 	lea	N.debug(b), a
       
  1397 	mov	a, deP(bp)			# save local -->Debug
       
  1398 	cmp	$1, N.closing(b)
       
  1399 	je	0f				# already closing, nothing to do
       
  1400 	LOG	5, "spawning thread to close client side"
       
  1401 	push	b				# -->this (param for thread)
       
  1402 	pushl	$N.closeCliThread		# -->thread func
       
  1403 	pushl	$0
       
  1404 	lea	N.ptid(b), a			# -->thread ID
       
  1405 	push	a
       
  1406 	call	pthread_create
       
  1407 	test	a, a
       
  1408 	jz	1f
       
  1409 	SYSERR	"create thread"
       
  1410 1:	mov	thisP(bp), b			# -->this Node
       
  1411 	movl	$1, N.closing(b)		# indicate "closing"
       
  1412 	push	N.ptid(b)
       
  1413 	LOG	5, "closing thread (%u) spawned"
       
  1414 0:	EPILOG
       
  1415 #-----------------------------------------------
       
  1416 #	C L O S E   C L I E N T   S I D E S
       
  1417 #-----------------------------------------------
       
  1418 	ARGS
       
  1419 	DS	thisP
       
  1420 	PROLOC
       
  1421 	DL	deP				# -->Debug inst
       
  1422 	DL	debug, DebugL
       
  1423 	EPILOC
       
  1424 #-----------------------------------------------
       
  1425 N.closeCliThread:
       
  1426 	PROLOG
       
  1427 	mov	thisP(bp), b			# -->this Node
       
  1428 	lea	debug(bp), a
       
  1429 	mov	a, deP(bp)			# save deP
       
  1430 	lea	N.debug(b), a
       
  1431 	lea	D.id(a), a			# -->caller debug id
       
  1432 	push	a
       
  1433 	DEBID	"%s CLOSE clients", 1
       
  1434 	LOG	5, "start..."
       
  1435 	mov	$0, c				# offet in socket info array
       
  1436 	mov	$0, d				# socket info rank
       
  1437 	mov	N.cliSideP(b), a		# -->client socket info array
       
  1438 0:						# iterate on opened sockets
       
  1439 	cmp	$-1, So.sc(a, c)		# sc allocated ?
       
  1440 	je	1f				# no, iterate
       
  1441 	push	So.sc(a, c)			# socket#
       
  1442 	LOG	4, "sc=%u"
       
  1443 	push	deP(bp)
       
  1444 	pushl	$0				# indicate "client"
       
  1445 	push	d				# socket info rank
       
  1446 	call	N.closeSocket			# close socket
       
  1447 1:	inc	d
       
  1448 	cmp	N.nodes(b), d			# rank < nodes ?
       
  1449 	je	0f				# no, end
       
  1450 	lea	SocketInfoL(c), c		# incr offset
       
  1451 	jmp	0b				# iterate
       
  1452 0:	LOG	4, "finished, exiting thread"
       
  1453 	pushl	$0
       
  1454 	call	pthread_exit
       
  1455 	EPILOG
       
  1456 #-----------------------------------------------
       
  1457 #	S Y N C H R O N I Z E   A L L   N O D E S
       
  1458 #-----------------------------------------------
       
  1459 	ARGS
       
  1460 	PROLOC
       
  1461 	DL	thisP
       
  1462 	DL	deP
       
  1463 	DL	shP
       
  1464 	DL	tosignal
       
  1465 	DL	sigmask, 128
       
  1466 	DL	sigact, SigActionL
       
  1467 	EPILOC
       
  1468 N.sync:
       
  1469 	PROLOG
       
  1470 	mov	b, thisP(bp)			# save -->this Node
       
  1471 	lea	N.debug(b), a
       
  1472 	mov	a, deP(bp)			# save -->Debug locally for LOG macro
       
  1473 
       
  1474 	movl	$0, tosignal(bp)
       
  1475 	mov	C.csP, c			# -->CS
       
  1476 	mov	C.shP(c), a			# -->shared mem
       
  1477 	push	S.act(a)
       
  1478 	mov	a, shP(bp)
       
  1479 	push	N.pid(b)
       
  1480 	LOG	5, "%u synchronizing: active=%u"
       
  1481 # set signal handler block
       
  1482 	lea	sigact(bp), a
       
  1483 	movl	$N.sighandle, sa_handler(a)
       
  1484 	movl	$0, sa_flags(a)
       
  1485 	lea	sa_mask(a), a			# set handler mask
       
  1486 	push	a
       
  1487 	SYS	sigfillset
       
  1488 	jmp	0f
       
  1489 N.sighandle:
       
  1490 	ret
       
  1491 0:
       
  1492 # activate signal handler
       
  1493 	lea	sigmask(bp), a
       
  1494 	push	a
       
  1495 	SYS	sigemptyset
       
  1496 	push	$SIGUSR2
       
  1497 	lea	sigmask(bp), a
       
  1498 	push	a
       
  1499 	SYS	sigaddset
       
  1500 	push	$0
       
  1501 	lea	sigmask(bp), a
       
  1502 	push	a
       
  1503 	push	$SIG_UNBLOCK
       
  1504 	SYS	sigprocmask
       
  1505 	push	$0
       
  1506 	lea	sigact(bp), a
       
  1507 	push	a
       
  1508 	push	$SIGUSR2
       
  1509 	SYS	sigaction
       
  1510 # update nodes counter
       
  1511 	mov	shP(bp), a
       
  1512 	lea	S.counter_sem(a), a
       
  1513 	push	a
       
  1514 	SYS	sem_wait			# get semaphore
       
  1515 	mov	shP(bp), a
       
  1516 	decl	S.act(a)			# decrement nodes counter
       
  1517 	setz	tosignal(bp)
       
  1518 	mov	shP(bp), a
       
  1519 	lea	S.counter_sem(a), a
       
  1520 	push	a
       
  1521 	SYS	sem_post			# post semaphore
       
  1522 	testl	$1, tosignal(bp)		# all finished?
       
  1523 	jz	N.sigwait
       
  1524 # signal all tasks
       
  1525 	push	N.pid(b)
       
  1526 	LOG	5, "%u signaling USR2"
       
  1527 	push	$SIGUSR2
       
  1528 	push	$0
       
  1529 	SYS	kill
       
  1530 	jmp	N.woken
       
  1531 # wait for signal
       
  1532 N.sigwait:
       
  1533 #	call	pause
       
  1534 	push	$5
       
  1535 	call	sleep
       
  1536 N.woken:
       
  1537 	mov	thisP(bp), b			# -->this Node
       
  1538 	push	N.pid(b)
       
  1539 	LOG	5, "%u woken up"
       
  1540 	EPILOG
       
  1541 #-----------------------------------------------
       
  1542 #	F O R M A T   A N D   P R I N T   S S L   E R R O R
       
  1543 #-----------------------------------------------
       
  1544 # args
       
  1545 	ac = 8
       
  1546 	DS	deP				# -->Debug
       
  1547 	DS	msgP				# -->accompanying msg str
       
  1548 # returns:	nothing
       
  1549 	PROLOC
       
  1550 	DL	str, 256			# generated string buf
       
  1551 	EPILOC
       
  1552 #-----------------------------------------------
       
  1553 	.global N.sslErr
       
  1554 N.sslErr:
       
  1555 	enter	$locL, $0
       
  1556 0:
       
  1557 	call	ERR_get_error
       
  1558 	push	a
       
  1559 	LOG	5, "ssl err, e=%lu", 1
       
  1560 	test	a, a				# end of msg queue ?
       
  1561 	jz	0f				# yes
       
  1562 	lea	str(bp), d
       
  1563 	push	d				# -->err msg str buf
       
  1564 	push	a				# err
       
  1565 	call	ERR_error_string
       
  1566 	push	a				# -->err msg str
       
  1567 	pushl	msgP(bp)			# -->accompanying msg str
       
  1568 	LOG	0, "%s: %s", 2
       
  1569 	jmp	0b				# iterate on SSL err msg queue
       
  1570 0:
       
  1571 	pushl	$1
       
  1572 	call	exit				# ABEND
       
  1573 #-----------------------------------------------
       
  1574 #	G E T   A S S I G N E D   I P   A D D R
       
  1575 #-----------------------------------------------
       
  1576 # puts assigned IP address:port in string
       
  1577 	ARGS
       
  1578 	DS	sP				# -->output string
       
  1579 	DS	saP				# -->sockaddr
       
  1580 	DS	deP				# -->Debug
       
  1581 # returns:	nothing
       
  1582 	PROLOC
       
  1583 	EPILOC
       
  1584 #-----------------------------------------------
       
  1585 gai:	PROLOG
       
  1586 
       
  1587 	mov	saP(bp), b			# -->sockaddr
       
  1588 	xor	a, a
       
  1589 	mov	sa_data(b), %ax			# port # in big endian order
       
  1590 	push	a
       
  1591 	call	ntohs
       
  1592 	mov	a, d
       
  1593 
       
  1594 	mov	saP(bp), b			# -->sockaddr
       
  1595 	pushl	sa_data+2(b)			# IP addr in big endian order
       
  1596 	call	ntohl
       
  1597 
       
  1598 	push	d				# port # as int
       
  1599 
       
  1600         mov     $4, c				# iterate on 4 bytes of IP addr
       
  1601 0:      mov     a, d
       
  1602         and     $0xff, d
       
  1603         push    d				# part of IP addr
       
  1604         shr     $8, a
       
  1605         dec     c
       
  1606         jnz     0b				# iterate
       
  1607 
       
  1608 	push	$0f
       
  1609 	pushl	sP(bp)				# -->output buf
       
  1610 	call	sprintf
       
  1611 	jmp	1f
       
  1612 0:	.ascii	"%u.%u.%u.%u:%d\0"
       
  1613 1:
       
  1614 	EPILOG
       
  1615 #-----------------------------------------------
       
  1616 	.end