/*
* Copyright (c) 2001-2006 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 1998-2001 University of Notre Dame.
* All rights reserved.
* Copyright (c) 1994-1998 The Ohio State University.
* All rights reserved.
*
* This file is part of the LAM/MPI software package. For license
* information, see the LICENSE file in the top level directory of the
* LAM/MPI source distribution.
*
* $HEADER$
*
* Function: - physical layer receive
* - receive messages on virtual circuits
* - OTB version (UNIX, STREAM sockets)
*
* - precvopen(): create VC to receive messages
* - precv(): receive message on VC
* - precvclose(): destroy receiver's VC
*/
#include <lam_config.h>
#include <sfh.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <etc_misc.h>
#include <portable.h>
#include <net.h>
#include <terror.h>
#include <typical.h>
#include <t_types.h>
#include <vctable.h>
#include <laminternal.h>
#ifndef TO_PRECVO_CONN
#define TO_PRECVO_CONN 100
#endif
/*
* external functions
*/
extern void _ltot_usrnmsg();
extern void _ltot_sysnmsg();
extern void _ttol_usrnmsg();
extern void _ttol_sysnmsg();
extern int sfh_sock_open_clt_inet_stm();
extern int _vcdelete();
extern int _vcinsert();
extern struct vcdesc *_vcfind();
/*
* precvopen
*
* Function: - create a virtual circuit for the receiver
* - works only between OTB nodes
* Accepts: - ptr network message descriptor
* Returns: - 0 or ERROR
*/
int
precvopen(nhead)
struct nmsg *nhead;
{
int vcsock = -1; /* VC socket */
int sndport; /* sender port # */
int i; /* favourite counter */
unsigned char sndaddr[4]; /* sender address */
struct nmsg protocol; /* protocol message */
/*
* Receive the virtual circuit protocol message.
*/
protocol.nh_event = nhead->nh_event;
protocol.nh_type = nhead->nh_type;
protocol.nh_flags = 0;
protocol.nh_length = 0;
protocol.nh_msg = 0;
if (nrecv(&protocol)) {
return(ERROR);
}
/*
* Modify the receiver's nh_type field to match the synchronization.
*/
nhead->nh_type = protocol.nh_type;
/*
* Let the sender know the receiver is ready.
*/
memcpy((char *) sndaddr, (char *) protocol.nh_data, 4);
ttoli4(&protocol.nh_data[1], &sndport);
ttoli4(&protocol.nh_data[2], &protocol.nh_node);
ttoli4(&protocol.nh_data[3], &protocol.nh_event);
protocol.nh_type = 0;
protocol.nh_data[0] = -lam_getpid();
if (nsend(&protocol)) {
return(ERROR);
}
/*
* Receive the OK-to-connect message from the sender.
*/
protocol.nh_event = -lam_getpid();
if (nrecv(&protocol)) {
return(ERROR);
}
/*
* Connect the virtual circuit.
* Keep trying till success or timeout.
*/
for (i = 0; i < TO_PRECVO_CONN; ++i) {
if ((vcsock =
sfh_sock_open_clt_inet_stm(sndaddr, sndport)) >= 0) {
break;
}
}
if (vcsock < 0) {
return(ERROR);
}
/*
* Insert the virtual circuit in the VC table.
*/
if (_vcinsert(LOCAL, nhead->nh_event, nhead->nh_type, vcsock)) {
close(vcsock);
return(ERROR);
}
return(0);
}
/*
* precv
*
* Function: - receive a network message on a virtual circuit
* Accepts: - ptr network message descriptor
* Returns: - 0 or ERROR
*/
int
precv(nhead)
struct nmsg *nhead;
{
struct nmsg incoming; /* incoming header */
struct vcdesc *p; /* favourite pointer */
int4 extra_len; /* extra msg length */
int4 nbytes; /* # bytes read */
int4 save_flags; /* saved nh_flags */
char bitbucket; /* to trash extra msg */
/*
* Locate the virtual circuit in the VC table.
*/
p = _vcfind(LOCAL, nhead->nh_event, nhead->nh_type);
if (p == 0) {
return(ERROR);
}
/*
* Receive the incoming message header.
*/
nbytes = mread(p->vc_path, (char *) &incoming, sizeof(struct nmsg));
if (nbytes < (int)sizeof(struct nmsg)) {
errno = (nbytes < 0) ? errno : EIO;
return(ERROR);
}
/*
* Convert the system part of the header to local byte order.
*/
_ttol_sysnmsg(&incoming);
/*
* Set the message length.
*/
if (nhead->nh_length > incoming.nh_length) {
nhead->nh_length = incoming.nh_length;
}
/*
* Copy the received data pouch as is (i.e. in Trollius byte order).
*/
memcpy((char *) nhead->nh_data,
(char *) incoming.nh_data, NHDSIZE * sizeof(int4));
/*
* Receive the user's message.
*/
if (nhead->nh_length > 0) {
nbytes = mread(p->vc_path, nhead->nh_msg, nhead->nh_length);
if (nbytes < nhead->nh_length) {
errno = (nbytes < 0) ? errno : EIO;
return(ERROR);
}
}
/*
* Use the incoming nh_flags to convert the message to local byte order.
* Restore the original nh_flags as given by the caller.
*/
save_flags = nhead->nh_flags;
nhead->nh_flags = incoming.nh_flags;
_ttol_usrnmsg(nhead);
nhead->nh_flags = save_flags;
/*
* Receive and trash any unused portion of the message sent.
*/
extra_len = incoming.nh_length - nhead->nh_length;
for ( ; extra_len > 0; --extra_len) {
nbytes = mread(p->vc_path, &bitbucket, (int4) 1);
if (nbytes < 1) {
errno = (nbytes < 0) ? errno : EIO;
return(ERROR);
}
}
return(0);
}
/*
* precvclose
*
* Function: - close a virtual circuit for the receiver
* Accepts: - ptr network message descriptor
* Returns: - 0 or ERROR
*/
int
precvclose(nhead)
struct nmsg *nhead;
{
struct vcdesc *p; /* favourite pointer */
/*
* Locate the virtual circuit entry in the VC table.
*/
p = _vcfind(LOCAL, nhead->nh_event, nhead->nh_type);
if (p == 0) {
return(ERROR);
}
/*
* Close the VC socket and delete the table entry.
*/
close(p->vc_path);
return(_vcdelete(LOCAL, nhead->nh_event, nhead->nh_type));
}
syntax highlighted by Code2HTML, v. 0.9.1