8#ifndef VRPN_USE_WINSOCK_SOCKETS
12#include <netinet/in.h>
54static const char *requestIndex_type =
"vrpn_Mutex Request Index";
55static const char *requestMutex_type =
"vrpn_Mutex Request Mutex";
56static const char *release_type =
"vrpn_Mutex Release";
57static const char *releaseNotification_type =
"vrpn_Mutex Release_Notification";
58static const char *grantRequest_type =
"vrpn_Mutex Grant_Request";
59static const char *denyRequest_type =
"vrpn_Mutex Deny_Request";
61static const char *initialize_type =
"vrpn_Mutex Initialize";
71static vrpn_uint32 getmyIP(
const char *NICaddress = NULL)
81 in.s_addr = inet_addr(NICaddress);
82 if (in.s_addr != INADDR_NONE) {
83 return ntohl(in.s_addr);
87 host = gethostbyname(NICaddress);
89 memcpy(&in.s_addr, host->h_addr, host->h_length);
90 return ntohl(in.s_addr);
93 fprintf(stderr,
"getmyIP: Can't get host entry for %s.\n", NICaddress);
97 retval = gethostname(myname,
sizeof(myname));
99 fprintf(stderr,
"getmyIP: Couldn't determine local hostname.\n");
106 host = gethostbyname(myname);
108 fprintf(stderr,
"getmyIP: Couldn't find host by name (%s).\n", myname);
112 memcpy(&in.s_addr, host->h_addr, host->h_length);
113 return ntohl(in.s_addr);
138 delete[] servicename;
140 fprintf(stderr,
"vrpn_Mutex::vrpn_Mutex(): delete failed\n");
231 vrpn_int32 droppedLast;
249 vrpn_int32 got, droppedLast;
274 fprintf(stderr,
"vrpn_Mutex_Server::handle_request from %d.\n", remoteId);
299 fprintf(stderr,
"vrpn_Mutex_Server::handle_release.\n");
314 vrpn_int32 msg_len =
sizeof(vrpn_int32) + p.
payload_len;
316 try { buffer =
new char[msg_len]; }
317 catch (...) {
return -1; }
319 vrpn_int32 bl = msg_len;
322 fprintf(stderr,
"vrpn_Mutex_Server::handle_requestIndex: "
323 "Initializing client %d (%lu %d).\n",
325 ntohl(*(vrpn_int32 *)(p.
buffer +
sizeof(vrpn_uint32))));
342 fprintf(stderr,
"vrpn_Mutex_Server::handle_requestIndex(): delete failed\n");
363 fprintf(stderr,
"vrpn_Mutex_Server::handle_dropLastConnection: "
364 "Forcing the state to FREE to avoid deadlock.\n");
373 :
vrpn_Mutex(name, c ? c : ((strcmp(name,
"null") == 0)
378 , d_requestBeforeInit(vrpn_FALSE)
379 , d_reqGrantedCB(NULL)
380 , d_reqDeniedCB(NULL)
443 vrpn_int32 buflen =
sizeof(vrpn_int32) +
sizeof(vrpn_uint32);
445 try { buf =
new char[buflen]; }
446 catch (...) {
return; }
448 vrpn_int32 len = buflen;
449 vrpn_uint32 ip_addr = getmyIP();
451 vrpn_int32 pid = _getpid();
453 vrpn_int32 pid = getpid();
458 printf(
"requesting index for %lu, %d\n", ip_addr, pid);
466 fprintf(stderr,
"vrpn_Mutex_Remote::requestIndex(): delete failed\n");
477 fprintf(stderr,
"Requested unavailable mutex.\n");
484 fprintf(stderr,
"Requested mutex before initialization; deferring.\n");
491 fprintf(stderr,
"Requesting mutex\n");
507 fprintf(stderr,
"Releasing mutex.\n");
521 fprintf(stderr,
"vrpn_Mutex_Remote::addRequestGrantedCallback: "
539 fprintf(stderr,
"vrpn_Mutex_Remote::addRequestDeniedCallback: "
557 "vrpn_Mutex_Remote::addTakeCallback: Out of memory.\n");
574 fprintf(stderr,
"vrpn_Mutex_Remote::addReleaseCallback: "
596 fprintf(stderr,
"vrpn_Mutex_Remote::handle_grantRequest for %d.\n", index);
622 fprintf(stderr,
"vrpn_Mutex_Remote::handle_denyRequest for %d.\n", index);
642 fprintf(stderr,
"vrpn_Mutex_Remote::handle_releaseNotification.\n");
663 vrpn_int32 expected_payload_len =
664 2 *
sizeof(vrpn_int32) +
sizeof(vrpn_uint32);
667 "vrpn_Mutex_Remote::handle_initialize: "
668 "Warning: Ignoring message with length %d, expected %d\n",
677 vrpn_int32 my_pid = 0;
683 if ((ip_addr != getmyIP()) || (pid != my_pid)) {
686 "vrpn_Mutex_Remote::handle_initialize: "
687 "Warning: Ignoring message that doesn't match ip/pid identifier\n");
689 fprintf(stderr,
"Got %lu %d, expected %lu %d.\n", ip_addr, pid,
697 fprintf(stderr,
"vrpn_Mutex_Remote::handle_initialize: "
698 "Got assigned index %d.\n",
704 fprintf(stderr,
"vrpn_Mutex_Remote::handle_initialize: "
705 "Sending request\n");
780 const char *NICaddress)
785 , d_numConnectionsAllocated(0)
786 , d_myIP(getmyIP(NICaddress))
790 , d_reqGrantedCB(NULL)
791 , d_reqDeniedCB(NULL)
798 fprintf(stderr,
"vrpn_PeerMutex: NULL name!\n");
803 sprintf(con_name,
"%s:%d", NICaddress, port);
810 fprintf(stderr,
"vrpn_PeerMutex: "
811 "Couldn't open connection on port %d!\n",
824 , d_numConnectionsAllocated(0)
825 , d_myIP(getmyIP(NULL))
829 , d_reqGrantedCB(NULL)
830 , d_reqDeniedCB(NULL)
837 fprintf(stderr,
"vrpn_PeerMutex: NULL name!\n");
844 fprintf(stderr,
"vrpn_PeerMutex: NULL connection!\n");
875 fprintf(stderr,
"vrpn_PeerMutex::~vrpn_PeerMutex(): delete failed\n");
888 fprintf(stderr,
"vrpn_PeerMutex::~vrpn_PeerMutex(): delete failed\n");
939 "vrpn_PeerMutex::request: the mutex isn't available.\n");
967 fprintf(stderr,
"vrpn_PeerMutex::request: requested the mutex "
968 "(from %d peers).\n",
982 fprintf(stderr,
"vrpn_PeerMutex::release: we don't hold the mutex.\n");
998 fprintf(stderr,
"vrpn_PeerMutex::release: released the mutex.\n");
1018 fprintf(stderr,
"vrpn_PeerMutex::addPeer: Out of memory.\n");
1029 fprintf(stderr,
"vrpn_PeerMutex::addPeer(): delete failed\n");
1037 fprintf(stderr,
"vrpn_PeerMutex::addPeer(): delete failed\n");
1047 try { d =
new losePeerData; }
1049 fprintf(stderr,
"vrpn_PeerMutex::addPeer: Out of memory.\n");
1061 fprintf(stderr,
"vrpn_PeerMutex::addPeer: added peer named %s.\n",
1074 fprintf(stderr,
"vrpn_PeerMutex::addRequestGrantedCallback: "
1075 "Out of memory.\n");
1091 fprintf(stderr,
"vrpn_PeerMutex::addRequestDeniedCallback: "
1092 "Out of memory.\n");
1108 fprintf(stderr,
"vrpn_PeerMutex::addTakeCallback: Out of memory.\n");
1125 fprintf(stderr,
"vrpn_PeerMutex::addReleaseCallback: "
1126 "Out of memory.\n");
1141 const char *b = p.
buffer;
1142 vrpn_uint32 senderIP;
1143 vrpn_uint32 senderPort;
1154 nad.s_addr = htonl(senderIP);
1156 "vrpn_PeerMutex::handle_request: got one from %s port %d.\n",
1157 inet_ntoa(nad), senderPort);
1194 const char *b = p.
buffer;
1195 vrpn_uint32 senderIP;
1196 vrpn_uint32 senderPort;
1204 nad.s_addr = senderIP;
1206 "vrpn_PeerMutex::handle_release: got one from %s port %d.\n",
1207 inet_ntoa(nad), senderPort);
1212 fprintf(stderr,
"vrpn_PeerMutex::handle_release: Got a release from "
1213 "somebody who didn't have the lock!?\n");
1229 const char *b = p.
buffer;
1230 vrpn_uint32 senderIP;
1231 vrpn_uint32 senderPort;
1238 nad.s_addr = senderIP;
1239 fprintf(stderr,
"vrpn_PeerMutex::handle_grantRequest: "
1240 "got one for %s port %d.\n",
1241 inet_ntoa(nad), senderPort);
1262 const char *b = p.
buffer;
1263 vrpn_uint32 senderIP;
1264 vrpn_uint32 senderPort;
1271 nad.s_addr = senderIP;
1272 fprintf(stderr,
"vrpn_PeerMutex::handle_denyRequest: "
1273 "got one for %s port %d.\n",
1274 inet_ntoa(nad), senderPort);
1293 losePeerData *data = (losePeerData *)userdata;
1306 if (c == me->
d_peer[i]) {
1312 "vrpn_PeerMutex::handle_losePeer: Can't find lost peer.\n");
1316 fprintf(stderr,
"vrpn_PeerMutex::handle_losePeer: lost peer #%d.\n", i);
1327 fprintf(stderr,
"vrpn_PeerMutex::handle_losePeer(): delete failed\n");
1451 size_t n = 1 + strlen(name);
1456 fprintf(stderr,
"vrpn_PeerMutex::init: Out of memory.\n");
Generic connection class not specific to the transport mechanism.
void addReference()
Counting references to this connection.
virtual vrpn_int32 register_message_type(const char *name)
virtual vrpn_bool connected(void) const
Returns vrpn_true if the connection has been established, vrpn_false if not (For a networkless connec...
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
virtual vrpn_int32 register_sender(const char *name)
Get a token to use for the string name of the sender or type. Remember to check for -1 meaning failur...
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
void setAutoDeleteStatus(bool setvalue)
Specify whether this connection should be deleted automatically when it is no longer need (reference ...
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
virtual int register_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Set up (or remove) a handler for a message of a given type. Optionally, specify which sender to handl...
void triggerTakeCallbacks(void)
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM)
vrpn_bool d_requestBeforeInit
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
virtual ~vrpn_Mutex_Remote(void)
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
mutexCallback * d_reqGrantedCB
void triggerReleaseCallbacks(void)
mutexCallback * d_reqDeniedCB
void triggerDenyCallbacks(void)
mutexCallback * d_releaseCB
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
void triggerGrantCallbacks(void)
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
static int VRPN_CALLBACK handle_releaseNotification(void *, vrpn_HANDLERPARAM)
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
vrpn_Mutex_Remote(const char *name, vrpn_Connection *=NULL)
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM)
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
virtual ~vrpn_Mutex_Server(void)
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM)
vrpn_Mutex_Server(const char *name, vrpn_Connection *=NULL)
static int VRPN_CALLBACK handle_dropLastConnection(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_requestMutex_type
vrpn_Connection * d_connection
vrpn_int32 d_release_type
vrpn_int32 d_initialize_type
vrpn_int32 d_requestIndex_type
void sendDenyRequest(vrpn_int32 index)
vrpn_int32 d_denyRequest_type
vrpn_Mutex(const char *name, vrpn_Connection *=NULL)
void sendRequest(vrpn_int32 index)
void sendReleaseNotification(void)
void sendGrantRequest(vrpn_int32 index)
vrpn_int32 d_grantRequest_type
virtual ~vrpn_Mutex(void)=0
vrpn_int32 d_releaseNotification_type
vrpn_Connection * d_server
Receive on this connection.
int d_numPeersGrantingLock
Counts the number of "grants" we've received after issuing a request; when this reaches d_numPeers,...
mutexCallback * d_releaseCB
void triggerTakeCallbacks(void)
void triggerReleaseCallbacks(void)
static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM)
void init(const char *name)
vrpn_bool addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
vrpn_bool addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
vrpn_bool addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
peerData * d_peerData
Needed only to clean up when a peer shuts down (mid-request). It isn't currently feasible to have all...
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
vrpn_bool addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
void triggerDenyCallbacks(void)
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
void triggerGrantCallbacks(void)
static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM)
mutexCallback * d_reqDeniedCB
vrpn_int32 d_release_type
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
vrpn_int32 d_denyRequest_type
void sendRequest(vrpn_Connection *)
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
vrpn_int32 d_grantRequest_type
void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
void sendRelease(vrpn_Connection *)
vrpn_PeerMutex(const char *name, int port, const char *NICaddress=NULL)
This constructor opens a new connection/port for the mutex.
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
void checkGrantMutex(void)
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
vrpn_int32 d_request_type
vrpn_bool addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex. (If several peers are competing for the m...
mutexCallback * d_reqGrantedCB
This structure is what is passed to a vrpn_Connection message callback.
const char * vrpn_CONTROL
vrpn_CONTROL is the sender used for notification messages sent to the user from the local VRPN implem...
vrpn_Connection * vrpn_create_server_connection(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name)
Create a server connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
char * vrpn_copy_service_name(const char *fullname)
const char * vrpn_dropped_last_connection
const char * vrpn_dropped_connection
vrpn_Connection * vrpn_get_connection_by_name(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name, const char *remote_in_logfile_name, const char *remote_out_logfile_name, const char *NIC_IPaddress, bool force_connection)
Create a client connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
const char * vrpn_got_connection
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message.
#define vrpn_gettimeofday