msgchannel.c 3.74 KB
Newer Older
1 2 3 4
#include "common.h"
#include "msgchannel.h"
#include "connection.h"

5 6 7 8 9 10 11 12 13 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef MINGW
#include <sys/uio.h>
#endif

#include <jni.h>

15
//
16 17 18

#ifdef MINGW

19
static inline ssize_t
20 21 22 23 24 25 26 27
__send (struct connection * conn, struct message * msg, void * header, const size_t header_size) {
	ssize_t sent = connection_send (conn, header, header_size);
	sent += connection_send (conn, msg->control, msg->control_size);
	sent += connection_send (conn, msg->classcode, msg->classcode_size);
	return sent;
}


28
static inline void
29 30 31 32 33 34 35
__recv (struct connection * conn, void * control, const size_t control_size, void * classcode, const size_t classcode_size) {
	connection_recv (conn, control, control_size);
	connection_recv (conn, classcode, classcode_size);
}

#else

36
static inline ssize_t
37 38 39 40 41 42 43 44 45 46 47
__send (struct connection * conn, struct message * msg, void * header, const size_t header_size) {
	struct iovec iovs [] = {
		{ .iov_base = header, .iov_len = header_size },
		{ .iov_base = (void *) msg->control, .iov_len = msg->control_size },
		{ .iov_base = (void *) msg->classcode, .iov_len = msg->classcode_size }
	};

	return connection_send_iov (conn, &iovs [0], sizeof_array (iovs));
}


48
static inline void
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
__recv (struct connection * conn, void * control, const size_t control_size, void * classcode, const size_t classcode_size) {
	struct iovec iovs [2] = {
		{ .iov_base = control, .iov_len = control_size },
		{ .iov_base = classcode, .iov_len = classcode_size }
	};

	connection_recv_iov (conn, &iovs [0], sizeof_array (iovs));
}

#endif /* !MINGW */


/**
 * Sends the given message to the remote instrumentation server
 * via the given connection. Returns the number of bytes sent.
 */
ssize_t
message_send (struct connection * conn, struct message * msg) {
	assert (conn != NULL);
	assert (msg != NULL);

70
	ldebug (
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
		"sending message: flags %08x, control %d, code %d ... ",
		msg->message_flags, msg->control_size, msg->classcode_size
	);

	//

	jint ints [] = {
		htonl (msg->message_flags),
		htonl (msg->control_size),
		htonl (msg->classcode_size)
	};

	ssize_t sent = __send (conn, msg, &ints [0], sizeof (ints));
	assert (sent == (ssize_t) (sizeof (ints) + msg->control_size + msg->classcode_size));

	//

88
	debug ("sent %ld bytes ... done\n", sent);
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
	return sent;
}



static inline uint8_t *
__alloc_buffer (size_t len) {
	//
	// Allocate a buffer with an extra (zeroed) byte, but only if the
	// requested buffer length is greater than zero. Return NULL otherwise.
	//
	if (len == 0) {
		return NULL;
	}

	//

	uint8_t * buf = (uint8_t *) malloc (len + 1);
	check_error (buf == NULL, "failed to allocate buffer");

	buf [len] = '\0';
	return buf;
}


/**
 * Receives a message from the remote instrumentation server.
 */
void
message_recv (struct connection * conn, struct message * msg) {
	assert (conn != NULL);
	assert (msg != NULL);

122
	ldebug ("receiving message: ");
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

	//
	// First, receive the flags, the control and class code sizes.
	// Second, receive the control and class code data.
	// The ordering of receive calls is determined by the protocol.
	//
	jint ints [3];
	connection_recv (conn, &ints [0], sizeof (ints));
	jint response_flags = ntohl (ints [0]);

	//

	jint control_size = ntohl (ints [1]);
	uint8_t * control = __alloc_buffer (control_size);

	jint classcode_size = ntohl (ints [2]);
	uint8_t * classcode = __alloc_buffer (classcode_size);

	__recv (conn, control, control_size, classcode, classcode_size);

	//
	// Update message fields only after the whole message was read.
	//
	msg->message_flags = response_flags;
	msg->control_size = control_size;
	msg->classcode_size = classcode_size;
	msg->control = control;
	msg->classcode = classcode;

	//

154
	debug (
155 156 157 158
		"flags %08x, control %d, code %d ... done\n",
		response_flags, control_size, classcode_size
	);
}