示例#1
0
isc_result_t omapi_connection_copyout (unsigned char *buf,
				       omapi_object_t *h,
				       unsigned size)
{
	unsigned bytes_remaining;
	unsigned bytes_this_copy;
	unsigned first_byte;
	omapi_buffer_t *buffer;
	unsigned char *bufp;
	int sig_flags = SIG_MODE_UPDATE;
	omapi_connection_object_t *c;
	isc_result_t status;

	if (!h || h -> type != omapi_type_connection)
		return ISC_R_INVALIDARG;
	c = (omapi_connection_object_t *)h;

	if (size > c -> in_bytes)
		return ISC_R_NOMORE;
	bufp = buf;
	bytes_remaining = size;
	buffer = c -> inbufs;

	while (bytes_remaining) {
		if (!buffer)
			return ISC_R_UNEXPECTED;
		if (BYTES_IN_BUFFER (buffer)) {
			if (buffer -> head == (sizeof buffer -> buf) - 1)
				first_byte = 0;
			else
				first_byte = buffer -> head + 1;

			if (first_byte > buffer -> tail) {
				bytes_this_copy = (sizeof buffer -> buf -
						   first_byte);
			} else {
				bytes_this_copy =
					buffer -> tail - first_byte;
			}
			if (bytes_this_copy > bytes_remaining)
				bytes_this_copy = bytes_remaining;
			if (bufp) {
				if (c -> in_key) {
					if (!c -> in_context)
						sig_flags |= SIG_MODE_INIT;
					status = omapi_connection_sign_data
						(sig_flags,
						 c -> in_key,
						 &c -> in_context,
						 (unsigned char *)
						 &buffer -> buf [first_byte],
						 bytes_this_copy,
						 (omapi_typed_data_t **)0);
					if (status != ISC_R_SUCCESS)
						return status;
				}

				memcpy (bufp, &buffer -> buf [first_byte],
					bytes_this_copy);
				bufp += bytes_this_copy;
			}
			bytes_remaining -= bytes_this_copy;
			buffer -> head = first_byte + bytes_this_copy - 1;
			c -> in_bytes -= bytes_this_copy;
		}
			
		if (!BYTES_IN_BUFFER (buffer))
			buffer = buffer -> next;
	}

	/* Get rid of any input buffers that we emptied. */
	buffer = (omapi_buffer_t *)0;
	while (c -> inbufs &&
	       !BYTES_IN_BUFFER (c -> inbufs)) {
		if (c -> inbufs -> next) {
			omapi_buffer_reference (&buffer,
						c -> inbufs -> next, MDL);
			omapi_buffer_dereference (&c -> inbufs -> next, MDL);
		}
		omapi_buffer_dereference (&c -> inbufs, MDL);
		if (buffer) {
			omapi_buffer_reference
				(&c -> inbufs, buffer, MDL);
			omapi_buffer_dereference (&buffer, MDL);
		}
	}
	return ISC_R_SUCCESS;
}
示例#2
0
isc_result_t omapi_connection_writer (omapi_object_t *h)
{
	unsigned bytes_this_write;
	int bytes_written;
	unsigned first_byte;
	omapi_buffer_t *buffer;
	omapi_connection_object_t *c;

	if (!h || h -> type != omapi_type_connection)
		return ISC_R_INVALIDARG;
	c = (omapi_connection_object_t *)h;

	/* Already flushed... */
	if (!c -> out_bytes)
		return ISC_R_SUCCESS;

	buffer = c -> outbufs;

	while (c -> out_bytes) {
		if (!buffer)
			return ISC_R_UNEXPECTED;
		if (BYTES_IN_BUFFER (buffer)) {
			if (buffer -> head == (sizeof buffer -> buf) - 1)
				first_byte = 0;
			else
				first_byte = buffer -> head + 1;

			if (first_byte > buffer -> tail) {
				bytes_this_write = (sizeof buffer -> buf -
						   first_byte);
			} else {
				bytes_this_write =
					buffer -> tail - first_byte;
			}
			bytes_written = write (c -> socket,
					       &buffer -> buf [first_byte],
					       bytes_this_write);
			/* If the write failed with EWOULDBLOCK or we wrote
			   zero bytes, a further write would block, so we have
			   flushed as much as we can for now.   Other errors
			   are really errors. */
			if (bytes_written < 0) {
				if (errno == EWOULDBLOCK || errno == EAGAIN)
					return ISC_R_SUCCESS;
				else if (errno == EPIPE)
					return ISC_R_NOCONN;
#ifdef EDQUOT
				else if (errno == EFBIG || errno == EDQUOT)
#else
				else if (errno == EFBIG)
#endif
					return ISC_R_NORESOURCES;
				else if (errno == ENOSPC)
					return ISC_R_NOSPACE;
				else if (errno == EIO)
					return ISC_R_IOERROR;
				else if (errno == EINVAL)
					return ISC_R_INVALIDARG;
				else if (errno == ECONNRESET)
					return ISC_R_SHUTTINGDOWN;
				else
					return ISC_R_UNEXPECTED;
			}
			if (bytes_written == 0)
				return ISC_R_SUCCESS;

#if defined (TRACING)
			if (trace_record ()) {
				isc_result_t status;
				trace_iov_t iov [2];
				int32_t connect_index;
				
				connect_index = htonl (c -> index);
				
				iov [0].buf = (char *)&connect_index;
				iov [0].len = sizeof connect_index;
				iov [1].buf = &buffer -> buf [buffer -> tail];
				iov [1].len = bytes_written;
				
				status = (trace_write_packet_iov
					  (trace_connection_input, 2, iov,
					   MDL));
				if (status != ISC_R_SUCCESS) {
					trace_stop ();
					log_error ("trace %s output: %s",
						   "connection",
						   isc_result_totext (status));
				}
			}
#endif

			buffer -> head = first_byte + bytes_written - 1;
			c -> out_bytes -= bytes_written;

			/* If we didn't finish out the write, we filled the
			   O.S. output buffer and a further write would block,
			   so stop trying to flush now. */
			if (bytes_written != bytes_this_write)
				return ISC_R_SUCCESS;
		}
			
		if (!BYTES_IN_BUFFER (buffer))
			buffer = buffer -> next;
	}
		
	/* Get rid of any output buffers we emptied. */
	buffer = (omapi_buffer_t *)0;
	while (c -> outbufs &&
	       !BYTES_IN_BUFFER (c -> outbufs)) {
		if (c -> outbufs -> next) {
			omapi_buffer_reference (&buffer,
						c -> outbufs -> next, MDL);
			omapi_buffer_dereference (&c -> outbufs -> next, MDL);
		}
		omapi_buffer_dereference (&c -> outbufs, MDL);
		if (buffer) {
			omapi_buffer_reference (&c -> outbufs, buffer, MDL);
			omapi_buffer_dereference (&buffer, MDL);
		}
	}
	return ISC_R_SUCCESS;
}
示例#3
0
isc_result_t omapi_disconnect (omapi_object_t *h,
			       int force)
{
	omapi_connection_object_t *c;

//ScenSim-Port//#ifdef DEBUG_PROTOCOL
//ScenSim-Port//	log_debug ("omapi_disconnect(%s)", force ? "force" : "");
//ScenSim-Port//#endif

	c = (omapi_connection_object_t *)h;
	if (c -> type != omapi_type_connection)
		return DHCP_R_INVALIDARG;

//ScenSim-Port//#if defined (TRACING)
//ScenSim-Port//	if (trace_record ()) {
//ScenSim-Port//		isc_result_t status;
//ScenSim-Port//		int32_t index;
//ScenSim-Port//
//ScenSim-Port//		index = htonl (c -> index);
//ScenSim-Port//		status = trace_write_packet (trace_disconnect,
//ScenSim-Port//					     sizeof index, (char *)&index,
//ScenSim-Port//					     MDL);
//ScenSim-Port//		if (status != ISC_R_SUCCESS) {
//ScenSim-Port//			trace_stop ();
//ScenSim-Port//			log_error ("trace_write_packet: %s",
//ScenSim-Port//				   isc_result_totext (status));
//ScenSim-Port//		}
//ScenSim-Port//	}
//ScenSim-Port//	if (!trace_playback ()) {
//ScenSim-Port//#endif
		if (!force) {
			/* If we're already disconnecting, we don't have to do
			   anything. */
			if (c -> state == omapi_connection_disconnecting)
				return ISC_R_SUCCESS;

			/* Try to shut down the socket - this sends a FIN to
			   the remote end, so that it won't send us any more
			   data.   If the shutdown succeeds, and we still
			   have bytes left to write, defer closing the socket
			   until that's done. */
//ScenSim-Port//			if (!shutdown (c -> socket, SHUT_RD)) {
//ScenSim-Port//				if (c -> out_bytes > 0) {
//ScenSim-Port//					c -> state =
//ScenSim-Port//						omapi_connection_disconnecting;
//ScenSim-Port//					return ISC_R_SUCCESS;
//ScenSim-Port//				}
//ScenSim-Port//			}
		}
		close (c -> socket);
//ScenSim-Port//#if defined (TRACING)
//ScenSim-Port//	}
//ScenSim-Port//#endif
	c -> state = omapi_connection_closed;

//ScenSim-Port//#if 0
//ScenSim-Port//	/*
//ScenSim-Port//	 * Disconnecting from the I/O object seems incorrect as it doesn't
//ScenSim-Port//	 * cause the I/O object to be cleaned and released.  Previous to
//ScenSim-Port//	 * using the isc socket library this wouldn't have caused a problem
//ScenSim-Port//	 * with the socket library we would have a reference to a closed
//ScenSim-Port//	 * socket.  Instead we now do an unregister to properly free the
//ScenSim-Port//	 * I/O object.
//ScenSim-Port//	 */
//ScenSim-Port//
//ScenSim-Port//	/* Disconnect from I/O object, if any. */
//ScenSim-Port//	if (h -> outer) {
//ScenSim-Port//		if (h -> outer -> inner)
//ScenSim-Port//			omapi_object_dereference (&h -> outer -> inner, MDL);
//ScenSim-Port//		omapi_object_dereference (&h -> outer, MDL);
//ScenSim-Port//	}
//ScenSim-Port//#else
	if (h->outer) {
		omapi_unregister_io_object(h);
	}
//ScenSim-Port//#endif

	/* If whatever created us registered a signal handler, send it
	   a disconnect signal. */
	omapi_signal (h, "disconnect", h);

	/* Disconnect from protocol object, if any. */
	if (h->inner != NULL) {
		if (h->inner->outer != NULL) {
			omapi_object_dereference(&h->inner->outer, MDL);
		}
		omapi_object_dereference(&h->inner, MDL);
	}

	/* XXX: the code to free buffers should be in the dereference
		function, but there is no special-purpose function to
		dereference connections, so these just get leaked */
	/* Free any buffers */
	if (c->inbufs != NULL) {
		omapi_buffer_dereference(&c->inbufs, MDL);
	}
	c->in_bytes = 0;
	if (c->outbufs != NULL) {
		omapi_buffer_dereference(&c->outbufs, MDL);
	}
	c->out_bytes = 0;

	return ISC_R_SUCCESS;
}