8 #ifndef VRPN_USE_WINSOCK_SOCKETS 12 #include <netinet/in.h> 21 #define INADDR_NONE -1 54 static const char *requestIndex_type =
"vrpn_Mutex Request Index";
55 static const char *requestMutex_type =
"vrpn_Mutex Request Mutex";
56 static const char *release_type =
"vrpn_Mutex Release";
57 static const char *releaseNotification_type =
"vrpn_Mutex Release_Notification";
58 static const char *grantRequest_type =
"vrpn_Mutex Grant_Request";
59 static const char *denyRequest_type =
"vrpn_Mutex Deny_Request";
61 static const char *initialize_type =
"vrpn_Mutex Initialize";
71 static 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);
137 delete[] servicename;
226 vrpn_int32 droppedLast;
244 vrpn_int32 got, droppedLast;
269 fprintf(stderr,
"vrpn_Mutex_Server::handle_request from %d.\n", remoteId);
294 fprintf(stderr,
"vrpn_Mutex_Server::handle_release.\n");
309 vrpn_int32 msg_len =
sizeof(vrpn_int32) + p.
payload_len;
310 char *buffer =
new char[msg_len];
312 vrpn_int32 bl = msg_len;
315 fprintf(stderr,
"vrpn_Mutex_Server::handle_requestIndex: " 316 "Initializing client %d (%lu %d).\n",
318 ntohl(*(vrpn_int32 *)(p.
buffer +
sizeof(vrpn_uint32))));
351 fprintf(stderr,
"vrpn_Mutex_Server::handle_dropLastConnection: " 352 "Forcing the state to FREE to avoid deadlock.\n");
361 :
vrpn_Mutex(name, c ? c : ((strcmp(name,
"null") == 0)
366 , d_requestBeforeInit(vrpn_FALSE)
367 , d_reqGrantedCB(NULL)
368 , d_reqDeniedCB(NULL)
431 vrpn_int32 buflen =
sizeof(vrpn_int32) +
sizeof(vrpn_uint32);
432 char *buf =
new char[buflen];
434 vrpn_int32 len = buflen;
435 vrpn_uint32 ip_addr = getmyIP();
437 vrpn_int32 pid = _getpid();
439 vrpn_int32 pid = getpid();
444 printf(
"requesting index for %lu, %d\n", ip_addr, pid);
458 fprintf(stderr,
"Requested unavailable mutex.\n");
465 fprintf(stderr,
"Requested mutex before initialization; deferring.\n");
472 fprintf(stderr,
"Requesting mutex\n");
488 fprintf(stderr,
"Releasing mutex.\n");
501 fprintf(stderr,
"vrpn_Mutex_Remote::addRequestGrantedCallback: " 517 fprintf(stderr,
"vrpn_Mutex_Remote::addRequestDeniedCallback: " 533 "vrpn_Mutex_Remote::addTakeCallback: Out of memory.\n");
548 fprintf(stderr,
"vrpn_Mutex_Remote::addReleaseCallback: " 569 fprintf(stderr,
"vrpn_Mutex_Remote::handle_grantRequest for %d.\n", index);
595 fprintf(stderr,
"vrpn_Mutex_Remote::handle_denyRequest for %d.\n", index);
615 fprintf(stderr,
"vrpn_Mutex_Remote::handle_releaseNotification.\n");
636 vrpn_int32 expected_payload_len =
637 2 *
sizeof(vrpn_int32) +
sizeof(vrpn_uint32);
640 "vrpn_Mutex_Remote::handle_initialize: " 641 "Warning: Ignoring message with length %d, expected %d\n",
650 vrpn_int32 my_pid = 0;
656 if ((ip_addr != getmyIP()) || (pid != my_pid)) {
659 "vrpn_Mutex_Remote::handle_initialize: " 660 "Warning: Ignoring message that doesn't match ip/pid identifier\n");
662 fprintf(stderr,
"Got %lu %d, expected %lu %d.\n", ip_addr, pid,
670 fprintf(stderr,
"vrpn_Mutex_Remote::handle_initialize: " 671 "Got assigned index %d.\n",
677 fprintf(stderr,
"vrpn_Mutex_Remote::handle_initialize: " 678 "Sending request\n");
753 const char *NICaddress)
758 , d_numConnectionsAllocated(0)
759 , d_myIP(getmyIP(NICaddress))
763 , d_reqGrantedCB(NULL)
764 , d_reqDeniedCB(NULL)
771 fprintf(stderr,
"vrpn_PeerMutex: NULL name!\n");
776 sprintf(con_name,
"%s:%d", NICaddress, port);
783 fprintf(stderr,
"vrpn_PeerMutex: " 784 "Couldn't open connection on port %d!\n",
797 , d_numConnectionsAllocated(0)
798 , d_myIP(getmyIP(NULL))
802 , d_reqGrantedCB(NULL)
803 , d_reqDeniedCB(NULL)
810 fprintf(stderr,
"vrpn_PeerMutex: NULL name!\n");
817 fprintf(stderr,
"vrpn_PeerMutex: NULL connection!\n");
902 "vrpn_PeerMutex::request: the mutex isn't available.\n");
930 fprintf(stderr,
"vrpn_PeerMutex::request: requested the mutex " 931 "(from %d peers).\n",
945 fprintf(stderr,
"vrpn_PeerMutex::release: we don't hold the mutex.\n");
961 fprintf(stderr,
"vrpn_PeerMutex::release: released the mutex.\n");
979 if (!newc || !newg) {
980 fprintf(stderr,
"vrpn_PeerMutex::addPeer: Out of memory.\n");
999 d =
new losePeerData;
1001 fprintf(stderr,
"vrpn_PeerMutex::addPeer: Out of memory.\n");
1013 fprintf(stderr,
"vrpn_PeerMutex::addPeer: added peer named %s.\n",
1024 fprintf(stderr,
"vrpn_PeerMutex::addRequestGrantedCallback: " 1025 "Out of memory.\n");
1039 fprintf(stderr,
"vrpn_PeerMutex::addRequestDeniedCallback: " 1040 "Out of memory.\n");
1054 fprintf(stderr,
"vrpn_PeerMutex::addTakeCallback: Out of memory.\n");
1069 fprintf(stderr,
"vrpn_PeerMutex::addReleaseCallback: " 1070 "Out of memory.\n");
1084 const char *b = p.
buffer;
1085 vrpn_uint32 senderIP;
1086 vrpn_uint32 senderPort;
1097 nad.s_addr = htonl(senderIP);
1099 "vrpn_PeerMutex::handle_request: got one from %s port %d.\n",
1100 inet_ntoa(nad), senderPort);
1137 const char *b = p.
buffer;
1138 vrpn_uint32 senderIP;
1139 vrpn_uint32 senderPort;
1147 nad.s_addr = senderIP;
1149 "vrpn_PeerMutex::handle_release: got one from %s port %d.\n",
1150 inet_ntoa(nad), senderPort);
1155 fprintf(stderr,
"vrpn_PeerMutex::handle_release: Got a release from " 1156 "somebody who didn't have the lock!?\n");
1172 const char *b = p.
buffer;
1173 vrpn_uint32 senderIP;
1174 vrpn_uint32 senderPort;
1181 nad.s_addr = senderIP;
1182 fprintf(stderr,
"vrpn_PeerMutex::handle_grantRequest: " 1183 "got one for %s port %d.\n",
1184 inet_ntoa(nad), senderPort);
1205 const char *b = p.
buffer;
1206 vrpn_uint32 senderIP;
1207 vrpn_uint32 senderPort;
1214 nad.s_addr = senderIP;
1215 fprintf(stderr,
"vrpn_PeerMutex::handle_denyRequest: " 1216 "got one for %s port %d.\n",
1217 inet_ntoa(nad), senderPort);
1236 losePeerData *data = (losePeerData *)userdata;
1249 if (c == me->
d_peer[i]) {
1255 "vrpn_PeerMutex::handle_losePeer: Can't find lost peer.\n");
1259 fprintf(stderr,
"vrpn_PeerMutex::handle_losePeer: lost peer #%d.\n", i);
1390 fprintf(stderr,
"vrpn_PeerMutex::init: Out of memory.\n");
vrpn_int32 d_denyRequest_type
static int VRPN_CALLBACK handle_requestIndex(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_denyRequest_type
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...
void triggerGrantCallbacks(void)
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
~vrpn_PeerMutex(void)
If isHeldLocally(), calls release().
void addPeer(const char *stationName)
Takes a VRPN station name of the form "<host>:<port>".
static int VRPN_CALLBACK handle_dropLastConnection(void *, vrpn_HANDLERPARAM)
void triggerTakeCallbacks(void)
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_int32 d_request_type
void sendRelease(vrpn_Connection *)
const char * vrpn_dropped_connection
vrpn_int32 d_releaseNotification_type
vrpn_Mutex(const char *name, vrpn_Connection *=NULL)
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
static int VRPN_CALLBACK handle_losePeer(void *, vrpn_HANDLERPARAM)
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...
void triggerGrantCallbacks(void)
void sendDenyRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
void checkGrantMutex(void)
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
vrpn_int32 d_requestMutex_type
void addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex. (If several peers are competing for the m...
void triggerDenyCallbacks(void)
mutexCallback * d_releaseCB
int d_numPeersGrantingLock
Counts the number of "grants" we've received after issuing a request; when this reaches d_numPeers,...
void init(const char *name)
vrpn_PeerMutex(const char *name, int port, const char *NICaddress=NULL)
This constructor opens a new connection/port for the mutex.
virtual ~vrpn_Mutex_Server(void)
static int VRPN_CALLBACK handle_requestMutex(void *, vrpn_HANDLERPARAM)
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
mutexCallback * d_reqDeniedCB
vrpn_Connection * d_connection
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
Generic connection class not specific to the transport mechanism.
vrpn_bool isHeldRemotely(void) const
True from when we grant the lock to another process in response to its request message until we recei...
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
void sendRequest(vrpn_int32 index)
void triggerReleaseCallbacks(void)
vrpn_int32 d_release_type
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...
vrpn_bool d_requestBeforeInit
const char * vrpn_dropped_last_connection
vrpn_Connection ** d_peer
Send on these connections to other Mutex's well-known-ports.
void addReleaseCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer releases the mutex.
static int VRPN_CALLBACK handle_initialize(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_initialize_type
This structure is what is passed to a vrpn_Connection message callback.
void sendDenyRequest(vrpn_int32 index)
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...
void setAutoDeleteStatus(bool setvalue)
Specify whether this connection should be deleted automatically when it is no longer need (reference ...
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
virtual ~vrpn_Mutex_Remote(void)
vrpn_int32 d_requestIndex_type
virtual vrpn_bool connected(void) const
Returns vrpn_true if the connection has been established, vrpn_false if not (For a networkless connec...
void sendGrantRequest(vrpn_Connection *, vrpn_uint32 IPnumber, vrpn_uint32 PortNumber)
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
void triggerTakeCallbacks(void)
const char * vrpn_got_connection
peerData * d_peerData
Needed only to clean up when a peer shuts down (mid-request). It isn't currently feasible to have all...
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
char * vrpn_copy_service_name(const char *fullname)
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
mutexCallback * d_reqDeniedCB
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
void addRequestDeniedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is denied.
static int VRPN_CALLBACK handle_release(void *, vrpn_HANDLERPARAM)
static int VRPN_CALLBACK handle_releaseNotification(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_grantRequest_type
vrpn_bool isAvailable(void) const
True from when release() is called or we receive a release message from another process until request...
#define vrpn_gettimeofday
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_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).
static int VRPN_CALLBACK handle_request(void *, vrpn_HANDLERPARAM)
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.
mutexCallback * d_reqGrantedCB
void addRequestGrantedCallback(void *userdata, int(*)(void *))
These callbacks are triggered when OUR request is granted.
virtual ~vrpn_Mutex(void)=0
vrpn_int32 d_release_type
vrpn_Mutex_Remote(const char *name, vrpn_Connection *=NULL)
vrpn_Mutex_Server(const char *name, vrpn_Connection *=NULL)
void release(void)
Release the distributed lock. Does nothing if !isHeldLocally() and there isn't a request pending.
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).
void sendRequest(vrpn_Connection *)
void triggerDenyCallbacks(void)
vrpn_bool isHeldLocally(void) const
True from when RequestGranted callbacks are triggered until release() is called.
void sendReleaseNotification(void)
void addReference()
Counting references to this connection.
mutexCallback * d_reqGrantedCB
virtual vrpn_int32 register_message_type(const char *name)
void sendGrantRequest(vrpn_int32 index)
vrpn_Connection * d_server
Receive on this connection.
void request(void)
Request the distributed lock. Does not request the lock if !isAvailable(), instead automatically trig...
void addTakeCallback(void *userdata, int(*)(void *))
These callbacks are triggered when ANY peer gets the mutex.
static int VRPN_CALLBACK handle_gotConnection(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_grantRequest_type
mutexCallback * d_releaseCB
int d_numConnectionsAllocated
Dynamic array size for d_peer and d_peerGrantedLock.
static int VRPN_CALLBACK handle_denyRequest(void *, vrpn_HANDLERPARAM)
vrpn_int32 d_remoteIndex
Counts remotes who have had IDs issued to them.
static int VRPN_CALLBACK handle_grantRequest(void *, vrpn_HANDLERPARAM)
void triggerReleaseCallbacks(void)