/* * Copyright (c) 1987, 1988, 1989 Stanford University * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Stanford not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Stanford makes no representations about * the suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A chief deputy manages the connection to an object space. */ #include #include #include #include #include #include #include ChiefDeputy::ChiefDeputy (Connection* c) { server = c; cur = 0; } ChiefDeputy::~ChiefDeputy () { Sync(); delete server; } Connection* ChiefDeputy::GetServer() { return server; } ObjectTag ChiefDeputy::Tag () { return 0; } /* * Flush the outgoing message buffer. */ void ChiefDeputy::Sync () { if (cur > 0) { server->Write(buffer, cur); cur = 0; } } /* * Allocate space in the buffer for a packet. */ void ChiefDeputy::Alloc (void*& dst, ObjectTag t, int op, int len) { register Packet* p; register int n, prev; n = WordAlign(len + sizeof(Packet)); prev = cur; cur += n; if (cur >= sizeof(buffer)) { if (prev == 0) { fprintf(stderr, "object too large to send\n"); exit(1); } server->Write(buffer, prev); prev = 0; cur = n; } p = (Packet*) &buffer[prev]; p->tag = t; p->op = op; p->count = 1; p->extend = 0; p->length = len; dst = &p[1]; } /* * Put a string into a given place in the buffer. * The length of the null-terminated string is rounded up to * a word boundary, adding nulls if necessary. * The total number of bytes written in the buffer is returned. */ int ChiefDeputy::PackString (const char* s, void* dst) { return PackString(s, strlen(s), dst); } int ChiefDeputy::PackString (const char* s, int len, void* dst) { register int n = WordAlign(len + 1); memmove(dst, s, len); if (n > len) { memset(((char*)dst) + len, 0, n - len); } return n; } /* * Short-hand for simple case when a message has no operands. */ void ChiefDeputy::Msg (ObjectTag t, int op) { void* msg; Alloc(msg, t, op, 0); } /* * Put a message in the buffer consisting of an op with a single string * as operand. This call is short-hand for a combination of * Alloc and PackString. */ void ChiefDeputy::StringMsg (ObjectTag t, int op, const char* s) { void* msg; int n; n = strlen(s) + 1; Alloc(msg, t, op, n); PackString(s, n, msg); } /* * Put an integer in the buffer consisting of an op with a single integer * as operand. */ void ChiefDeputy::IntegerMsg (ObjectTag t, int op, int val) { void* msg; Alloc(msg, t, op, sizeof(int)); int* v = (int*)msg; *v = val; } /* * Try to read a certain size reply. Return the actual size read. */ int ChiefDeputy::ReadReply (void* reply, int len) { register int n, t; register char* p; Sync(); p = (char*)reply; t = len; do { n = server->Read(p, t); if (n <= 0) { return len - t; } p += n; t -= n; } while (t > 0); return len; } /* * Wait for a reply of a certain size from the server. */ void ChiefDeputy::GetReply (void* reply, int len) { if (ReadReply(reply, len) != len) { fprintf(stderr, "premature eof in GetReply\n"); exit(1); } } /* * Read a string of the given length, including any padding * for alignment. Space for the string is allocated here; * it is up to the caller to deallocate it. */ void ChiefDeputy::GetString (const char*& str, int len) { register int n = WordAlign(len); char* s = new char[n+1]; s[n] = '\0'; GetReply(s, n); str = s; }