Ejemplo n.º 1
0
Archivo: hooks.c Proyecto: op5/merlin
static int is_dupe(merlin_event *pkt)
{
	if (!check_dupes) {
		return 0;
	}

	if (last_pkt.hdr.type != pkt->hdr.type) {
		return 0;
	}

	if (packet_size(&last_pkt) != packet_size(pkt)) {
		return 0;
	}

	/* if this is truly a dupe, return 1 and log every 100'th */
	if (!memcmp(&last_pkt, pkt, packet_size(pkt))) {
		dupe_bytes += packet_size(pkt);
		if (!(++dupes % 100)) {
			ldebug("%s in %llu duplicate packets dropped",
				   human_bytes(dupe_bytes), dupes);
		}
		return 1;
	}

	return 0;
}
Ejemplo n.º 2
0
Archivo: node.c Proyecto: ageric/merlin
/*
 * Send the given event "pkt" to the node "node", or take appropriate
 * actions on the node itself in case sending fails.
 * Returns 0 on success, and < 0 otherwise.
 */
int node_send_event(merlin_node *node, merlin_event *pkt, int msec)
{
	int result;

	node_log_event_count(node, 0);

	if (packet_size(pkt) > TOTAL_PKT_SIZE) {
		lerr("header is invalid, or packet is too large. aborting");
		return -1;
	}

	if (node->sock < 0 || node->state != STATE_CONNECTED) {
		return node_binlog_add(node, pkt);
	}

	/*
	 * msec less than zero means the caller has already polled the
	 * socket, which should also mean it's connected
	 */
	if (msec >= 0 && !io_write_ok(node->sock, msec)) {
		return node_binlog_add(node, pkt);
	}

	if (is_module && is_stalling()) {
		return node_binlog_add(node, pkt);
	}

	/* if binlog has entries, we must send those first */
	if (binlog_has_entries(node->binlog)) {
		node_send_binlog(node, pkt);
	}

	/* binlog may still have entries. If so, add to it and return */
	if (binlog_has_entries(node->binlog))
		return node_binlog_add(node, pkt);

	result = node_send(node, pkt, packet_size(pkt), MSG_DONTWAIT);

	/* successfully sent, so add it to the counter and return 0 */
	if (result == packet_size(pkt)) {
		node->stats.events.sent++;
		return 0;
	}

	/*
	 * zero size writes and write errors get stashed in binlog.
	 * From the callers point of view, this counts as a success.
	 */
	if (result <= 0 && !node_binlog_add(node, pkt))
		return 0;

	/* node_send will have marked the node as out of sync now */
	return -1;
}
Ejemplo n.º 3
0
Archivo: node.c Proyecto: ageric/merlin
static int node_binlog_add(merlin_node *node, merlin_event *pkt)
{
	int result;

	/*
	 * we skip stashing some packet types in the binlog. Typically
	 * those that get generated immediately upon reconnect anyway
	 * since they would just cause unnecessary overhead and might
	 * trigger a lot of unnecessary actions if stashed.
	 */
	if (pkt->hdr.type == CTRL_PACKET) {
		if (pkt->hdr.code == CTRL_ACTIVE || pkt->hdr.code == CTRL_INACTIVE)
			return 0;
	}

	if (!node->binlog) {
		char *path;

		/* +20 to safely accommodate for "/.module.binlog\0" */
		path = calloc(1, strlen(binlog_dir) + strlen(node->name) + 20);
		sprintf(path, "%s/%s.%s.binlog",
		        binlog_dir, is_module ? "module" : "daemon", node->name);
		linfo("Creating binary backlog for %s. On-disk location: %s",
			  node->name, path);

		/* 10MB in memory, 100MB on disk */
		node->binlog = binlog_create(path, 10 << 20, 100 << 20, BINLOG_UNLINK);
		if (!node->binlog) {
			lerr("Failed to create binary backlog for %s: %s",
				 node->name, strerror(errno));
			return -1;
		}
		free(path);
	}

	result = binlog_add(node->binlog, pkt, packet_size(pkt));
	if (result < 0) {
		binlog_wipe(node->binlog, BINLOG_UNLINK);
		/* XXX should mark node as unsynced here */
		node->stats.events.dropped += node->stats.events.logged + 1;
		node->stats.bytes.dropped += node->stats.bytes.logged + packet_size(pkt);
		node->stats.events.logged = 0;
		node->stats.bytes.logged = 0;
	} else {
		node->stats.events.logged++;
		node->stats.bytes.logged += packet_size(pkt);
	}

	node_log_event_count(node, 0);

	return result;
}
Ejemplo n.º 4
0
QByteArray Message::createPacket() const
{
    QByteArray packet;
    qint32 packet_size(0);
    QDataStream out(&packet, QIODevice::WriteOnly );

    //qDebug() << Q_FUNC_INFO << "\n ----------------- Create packet ---------------------\n";
    out.setVersion(QDataStream::Qt_4_0);
    // Вставим размер пакета равный нулю, но отведем под него 8 байт
    
    out << packet_size;

    //Вставим Тип сообщения и само сообщение в пакет
    //qDebug()  << "\n (qint32) packet type  " << ( qint32 ) this->getType();
    out << ( qint32 ) this->getType();
    //qDebug()  << "\n message data_size  " << this->msgData.size();
    out << this->msgData;
    // возврат на начало блока
    out.device()->seek(0);
    // Вычислим размер блока данных и запишем их на свое место
    packet_size =(qint32)(packet.size() - sizeof(qint32));
    out << ( qint32 )  packet_size;
    /*
    qDebug() << "data size " << packet_size;
    qDebug() << "all packet size "  << (qint32)(packet.size() + sizeof(qint32));
    qDebug() << "------------- end create packet -----------------------\n";
    */
    return packet;
}
Ejemplo n.º 5
0
int main(int argc, char** argv) {
	bool bShutdown = false;
	fprintf(stderr, "Entering the loop.\n");
	while ( !bShutdown ) {
		byte_t packet_size_buff[ERL_MSG_HEADER_SIZE];
		byte_t packet_payload[ERL_MSG_MAX_SIZE];
		ssize_t bytes_read = 0;
		bytes_read = read(fileno(stdin), (void*) packet_size_buff, ERL_MSG_HEADER_SIZE);
		if ( bytes_read > 0 ) {
			size_t bytes_to_read = packet_size(packet_size_buff);
			fprintf(stderr, "Packet size: %d\n", bytes_to_read);

			bytes_read = read(fileno(stdin), (void*) packet_payload, bytes_to_read);
			if ( bytes_read != bytes_to_read ) {
				// fprintf(stderr, "wrong bytes_read: %d. Expected: %d\n. Errno: %s\n", bytes_read, bytes_to_read, strerror(errno));
				bShutdown = true;
			}
			else {
				// process(packet_payload, bytes_to_read);
			}
		}
		else {
			fprintf(stderr, "Error: %s\n", strerror(errno));
			bShutdown = true;
		}
	}
	fprintf(stderr, "Left the loop. Quitting.\n");
}
Ejemplo n.º 6
0
Archivo: hooks.c Proyecto: op5/merlin
/**
 * hold_notification_packet() makes a deep copy of a notification message and
 * stores it in a global variable tmp_notif_data. The purpose is to make it
 * possible to send notification messages the triggering check result.
 * Meaning that if a processed check result generates a notification, the
 * notification will be stored and sent once the ending check result is sent.
 * Without this the check result will be sent right after the notification
 * packet making the receiver overwrite any information stored from the
 * notification packet.
 */
static int hold_notification_packet(merlin_event *pkt, nebstruct_notification_data *data)
{
	if(tmp_notif_data) {
		return -1;	/* there is already some stored notification, bailing */
	}

	if (data->notification_type == HOST_NOTIFICATION) {
		ldebug("holding host notification for %s", data->host_name);
	} else {
		ldebug("holding service notification for %s;%s",
				data->service_description, data->host_name);
	}

	/* copy the notification data to storage */
	memcpy(&tmp_notif_pkt, pkt, packet_size(pkt));
	tmp_notif_data = malloc(sizeof(nebstruct_notification_data));
	memcpy(tmp_notif_data, data, sizeof(nebstruct_notification_data));
	tmp_notif_data->host_name = data->host_name ? strdup(data->host_name) : NULL;
	tmp_notif_data->service_description = data->service_description ? strdup(data->service_description) : NULL;
	tmp_notif_data->output = data->output ? strdup(data->output) : NULL;
	tmp_notif_data->ack_author = data->ack_author ? strdup(data->ack_author) : NULL;
	tmp_notif_data->ack_data = data->ack_data ? strdup(data->ack_data) : NULL;

	return 0;
}
Ejemplo n.º 7
0
Archivo: net.c Proyecto: pzl/piwm
static char *recv_finish_packet(int sock, Buffer *buffer) {
    char *pack_start;
    uint32_t pack_size;
    ssize_t n_recvd;

    pack_start = buffer->buf_end;

    while ( (n_recvd = recv(sock, buffer->buf_end, (BUF_ALLOC_SIZE - (buffer->buf_end - buffer->next_boundary)), 0)) > 0) {
        buffer->buf_end += n_recvd;

        //check for oversized packets
        if ( buffer->buf_end - buffer->buf >= BUF_ALLOC_SIZE ) {
            fprintf(stderr, "packet is larger than buffer!\n");
            return NULL;
        }

        //didn't even get full SIZE header, ask for more
        if ( buffer->buf_end - pack_start < PACK_HEAD_SIZE) {
            continue;
        }

        //get the final packet size
        pack_size = packet_size(buffer->buf);

        //have we read enough to encompass the packet?
        if ((uint32_t)(buffer->buf_end - pack_start) < pack_size) {
            continue; //not enough yet
        } else {
            break; // we got it!
        }


    }
    if (n_recvd == 0) {
        fprintf(stderr, "client disconnect\n");
        return NULL;
    } else if (n_recvd < 0) {
        perror("recv (finish packet)");
        return NULL;
    }

    if ((uint32_t)(buffer->buf_end - pack_start) < pack_size) {
        return NULL; //didn't get the whole packet, and didn't catch it in the loop. panic
    } else if ((uint32_t)(buffer->buf_end - pack_start) > pack_size) {
        buffer->next_boundary = pack_start + pack_size; //we started reading into the next packet
    } else {
        //we matched packet length exactly. next packet can start at buffer start
        buffer->buf_end = buffer->buf;
        buffer->next_boundary = NULL;
    }

    return pack_start;
}
Ejemplo n.º 8
0
unsigned char *get_hub_query_cmd(size_t byte_count, size_t *buf_size)
{
  unsigned char hub_query_cmd[] = {
    0x01, 0x85, 0xf0, 0x10, 0x8f, 0x30, 0x0e, 0x00, 0x60, 0x82, 0x10, 0xde, 0x01, 0x81, 0x30, 0x8f, 0x30,
    0x0c, 0x00, 0x60, 0x82, 0x10, 0x43, 0x00, 0x80, 0xa2, 0x00, 0x00, 0x81, 0x30, 0x82, 0x10, 0x43, 0x00,
    0x80, 0xa2, 0x00, 0x00, 0x81, 0x30, 0x82, 0x10, 0x43, 0x00, 0x80, 0xa2, 0x00, 0x00, 0x81, 0x30, 0x82,
    0x10, 0x43, 0x00, 0x80, 0xa2, 0x00, 0x00, 0x81, 0x30, 0x82, 0x10, 0x43, 0x00, 0x80, 0xa2, 0x00, 0x00,
    0x81, 0x30, 0x82, 0x10, 0x43, 0x00, 0x80, 0xa2, 0x00, 0x00, 0x81, 0x30, 0x82, 0x10, 0x43, 0x00, 0x80,
    0xa2, 0x00, 0x00, 0x81, 0x30, 0x82, 0x10, 0x43, 0x00, 0xc0, 0xa2, 0x00, 0x00, 0x81, 0x30,
  };

  size_t len = sizeof(hub_query_cmd) / sizeof(*hub_query_cmd);
  *buf_size = packet_size(len);
  return packetize(hub_query_cmd, len, 1);
}
Ejemplo n.º 9
0
unsigned char *packetize(unsigned char *the_bytes, size_t len, int channel)
{
  size_t packet_len = packet_size(len);
  unsigned char *packet = new unsigned char[packet_len];
  packet[0] = 0x7C;
  packet[1] = (unsigned char)channel;
  packet[2] = 0x7A;
  for (int i = 0; i < len; ++i)
    packet[i + 3] = the_bytes[i];

  packet[packet_len - 1] = packet[packet_len - 2];
  packet[packet_len - 2] = 0x7B;

  return packet;
}
Ejemplo n.º 10
0
int ipc_binlog_add(merlin_event *pkt)
{
	if (!ipc_binlog) {
		char *path;

		asprintf(&path, "/opt/monitor/op5/merlin/binlogs/ipc.%s.binlog",
				 is_module ? "module" : "daemon");

		/* 1MB in memory, 100MB on disk */
		ipc_binlog = binlog_create(path, 1 << 20, 100 << 20, BINLOG_UNLINK);
		free(path);

		if (!ipc_binlog)
			return -1;
	}

	binlog_add(ipc_binlog, pkt, packet_size(pkt));
	return 0;
}
Ejemplo n.º 11
0
//! tries to convert the available bytes into a valid AuthHandler LinkLevelEvent.
SEGSEvent * AuthLink::bytes_to_event()
{
    uint16_t  packet_size(0);
    uint8_t * tmp(nullptr);

    while(true) // we loop and loop and loop loopy loop through the buffery contents!
    {
        if(m_received_bytes_storage.GetReadableDataSize()<=2) // no more bytes for us, so we'll go hungry for a while
            return nullptr;
        // And the skies are clear on the Packet Fishing Waters
        m_received_bytes_storage.uGet(packet_size); // Ah ha! I smell packet in there!
        if(m_received_bytes_storage.GetReadableDataSize()<packet_size) // tis' a false trail capt'n !
        {
            m_received_bytes_storage.PopFront(1); // Crew, Dead Slow Ahead ! we're in hunting mode !
            continue;
        }
        // this might be a live packet in there
        tmp = m_received_bytes_storage.GetBuffer()+2;

        m_codec.XorDecodeBuf(tmp, packet_size+1); // Let's see what's in those murky waters
        eAuthPacketType recv_type = OpcodeToType(tmp[0]);
        AuthLinkEvent *evt = AuthEventFactory::EventForType(recv_type); // Crow's nest, report !
        if(!evt)
        {
            if(m_received_bytes_storage.GetReadableDataSize()>2) // False alarm Skipper!
                m_received_bytes_storage.uGet(packet_size); // On to next adventure crew. Slow Ahead !
            continue;
        }
        // A catch !
        if(evt->type() == evLogin) // Is tis' on of those pesky AuthLogin Packets ?!!?
        {
            // Bring out the Codec Cannon, an' load it with Des
            m_codec.DesDecode(tmp+1,30); // It'll crack it's chitinous armor
        }
        evt->serializefrom(m_received_bytes_storage);
        m_received_bytes_storage.PopFront(packet_size+3); //Let's sail away from this depleted fishery.
        return evt; // And throw our catch to the Cook.
    }
}
Ejemplo n.º 12
0
	void http_seed_connection::on_receive(error_code const& error
		, std::size_t bytes_transferred)
	{
		INVARIANT_CHECK;

		if (error)
		{
			m_statistics.received_bytes(0, bytes_transferred);
#ifdef TORRENT_VERBOSE_LOGGING
			peer_log("*** http_seed_connection error: %s", error.message().c_str());
#endif
			return;
		}

		boost::shared_ptr<torrent> t = associated_torrent().lock();
		TORRENT_ASSERT(t);

		for (;;)
		{
			buffer::const_interval recv_buffer = receive_buffer();

			if (bytes_transferred == 0) break;
			TORRENT_ASSERT(recv_buffer.left() > 0);

			TORRENT_ASSERT(!m_requests.empty());
			if (m_requests.empty())
			{
				m_statistics.received_bytes(0, bytes_transferred);
				disconnect(errors::http_error, 2);
				return;
			}

			peer_request front_request = m_requests.front();

			bool header_finished = m_parser.header_finished();
			if (!header_finished)
			{
				bool parse_error = false;
				int protocol = 0;
				int payload = 0;
				boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, parse_error);
				m_statistics.received_bytes(0, protocol);
				bytes_transferred -= protocol;
				if (payload > front_request.length) payload = front_request.length;

				if (parse_error)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					disconnect(errors::http_parse_error, 2);
					return;
				}

				TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
			
				TORRENT_ASSERT(recv_buffer.left() <= packet_size());
				
				// this means the entire status line hasn't been received yet
				if (m_parser.status_code() == -1)
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}

				// if the status code is not one of the accepted ones, abort
				if (!is_ok_status(m_parser.status_code()))
				{
					int retry_time = atoi(m_parser.header("retry-after").c_str());
					if (retry_time <= 0) retry_time = 5 * 60;
					// temporarily unavailable, retry later
					t->retry_web_seed(this, retry_time);

					std::string error_msg = to_string(m_parser.status_code()).elems
						+ (" " + m_parser.message());
					if (m_ses.m_alerts.should_post<url_seed_alert>())
					{
						m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
							, error_msg));
					}
					m_statistics.received_bytes(0, bytes_transferred);
					disconnect(error_code(m_parser.status_code(), get_http_category()), 1);
					return;
				}
				if (!m_parser.header_finished())
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}
			}

			// we just completed reading the header
			if (!header_finished)
			{
				if (is_redirect(m_parser.status_code()))
				{
					// this means we got a redirection request
					// look for the location header
					std::string location = m_parser.header("location");
					m_statistics.received_bytes(0, bytes_transferred);

					if (location.empty())
					{
						// we should not try this server again.
						t->remove_web_seed(this);
						disconnect(errors::missing_location, 2);
						return;
					}
					
					// add the redirected url and remove the current one
					t->add_web_seed(location, web_seed_entry::http_seed);
					t->remove_web_seed(this);
					disconnect(errors::redirecting, 2);
					return;
				}

				std::string const& server_version = m_parser.header("server");
				if (!server_version.empty())
				{
					m_server_string = "URL seed @ ";
					m_server_string += m_host;
					m_server_string += " (";
					m_server_string += server_version;
					m_server_string += ")";
				}

				m_response_left = atol(m_parser.header("content-length").c_str());
				if (m_response_left == -1)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					// we should not try this server again.
					t->remove_web_seed(this);
					disconnect(errors::no_content_length, 2);
					return;
				}
				if (m_response_left != front_request.length)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					// we should not try this server again.
					t->remove_web_seed(this);
					disconnect(errors::invalid_range, 2);
					return;
				}
				m_body_start = m_parser.body_start();
			}

			recv_buffer.begin += m_body_start;

			// =========================
			// === CHUNKED ENCODING  ===
			// =========================
			while (m_parser.chunked_encoding()
				&& m_chunk_pos >= 0
				&& m_chunk_pos < recv_buffer.left())
			{
				int header_size = 0;
				size_type chunk_size = 0;
				buffer::const_interval chunk_start = recv_buffer;
				chunk_start.begin += m_chunk_pos;
				TORRENT_ASSERT(chunk_start.begin[0] == '\r' || is_hex(chunk_start.begin, 1));
				bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
				if (!ret)
				{
					TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.left() - m_partial_chunk_header));
					bytes_transferred -= chunk_start.left() - m_partial_chunk_header;
					m_statistics.received_bytes(0, chunk_start.left() - m_partial_chunk_header);
					m_partial_chunk_header = chunk_start.left();
					if (bytes_transferred == 0) return;
					break;
				}
				else
				{
#ifdef TORRENT_VERBOSE_LOGGING
					peer_log("*** parsed chunk: %d header_size: %d", chunk_size, header_size);
#endif
					TORRENT_ASSERT(bytes_transferred >= size_t(header_size - m_partial_chunk_header));
					bytes_transferred -= header_size - m_partial_chunk_header;

					m_statistics.received_bytes(0, header_size - m_partial_chunk_header);
					m_partial_chunk_header = 0;
					TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
					// cut out the chunk header from the receive buffer
					TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
					cut_receive_buffer(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
					recv_buffer = receive_buffer();
					recv_buffer.begin += m_body_start;
					m_chunk_pos += chunk_size;
					if (chunk_size == 0)
					{
						TORRENT_ASSERT(receive_buffer().left() < m_chunk_pos + m_body_start + 1
							|| receive_buffer()[int(m_chunk_pos + m_body_start)] == 'H'
							|| (m_parser.chunked_encoding() && receive_buffer()[int(m_chunk_pos + m_body_start)] == '\r'));
						m_chunk_pos = -1;
					}
				}
			}

			int payload = bytes_transferred;
			if (payload > m_response_left) payload = int(m_response_left);
			if (payload > front_request.length) payload = front_request.length;
			m_statistics.received_bytes(payload, 0);
			incoming_piece_fragment(payload);
			m_response_left -= payload;

			if (m_parser.status_code() == 503)
			{
				if (!m_parser.finished()) return;

				int retry_time = atol(std::string(recv_buffer.begin, recv_buffer.end).c_str());
				if (retry_time <= 0) retry_time = 60;
#ifdef TORRENT_VERBOSE_LOGGING
				peer_log("*** retrying in %d seconds", retry_time);
#endif

				m_statistics.received_bytes(0, bytes_transferred);
				// temporarily unavailable, retry later
				t->retry_web_seed(this, retry_time);
				disconnect(error_code(m_parser.status_code(), get_http_category()), 1);
				return;
			}


			// we only received the header, no data
			if (recv_buffer.left() == 0) break;

			if (recv_buffer.left() < front_request.length) break;

			// if the response is chunked, we need to receive the last
			// terminating chunk and the tail headers before we can proceed
			if (m_parser.chunked_encoding() && m_chunk_pos >= 0) break;

			m_requests.pop_front();
			incoming_piece(front_request, recv_buffer.begin);
			if (associated_torrent().expired()) return;

			int size_to_cut = m_body_start + front_request.length;
			TORRENT_ASSERT(receive_buffer().left() < size_to_cut + 1
				|| receive_buffer()[size_to_cut] == 'H'
				|| (m_parser.chunked_encoding() && receive_buffer()[size_to_cut] == '\r'));

			cut_receive_buffer(size_to_cut, t->block_size() + 1024);
			if (m_response_left == 0) m_chunk_pos = 0;
			else m_chunk_pos -= front_request.length;
			bytes_transferred -= payload;
			m_body_start = 0;
			if (m_response_left > 0) continue;
			TORRENT_ASSERT(m_response_left == 0);
			m_parser.reset();
		}
	}
Ejemplo n.º 13
0
Archivo: net.c Proyecto: pzl/piwm
/*
	@param:
		sock: socket to read from
		buffer: internal buffer, just keep giving it back to us and don't screw with it
		bufp: we will point this to the start of your requested packet, excluding the header

	@return
		0: Client disconnected or serious error. You should shut down the socket
	   >0: length of packet (in bytes), excluding the header
*/
uint32_t get_packet(int sock, Buffer *buffer, char **bufp) {
    uint32_t pack_size = 0;


    //on first read, buf will be uninitialized
    if (buffer->buf == NULL) {
        printf("initializing buffer\n");
        buffer->buf = calloc(BUF_ALLOC_SIZE,1); //init the space we'll need to read everything into

        buffer->next_boundary = NULL; //when NULL, means there isn't a partial packet to pull from
        buffer->buf_end = buffer->buf; //we haven't read anything, so the end is the beginning
    }


    printf("Buffer start addr: %p, Buffer next read addr: %p, Buffer next packet start: %p\n", buffer->buf, buffer->buf_end, buffer->next_boundary);

    //if there are pending packets existing in the buffer
    if (buffer->next_boundary != NULL) {
        printf("there may be cached packets\n");

        //check length, download anything necessary to finish
        if (buffer->buf_end - buffer->next_boundary < PACK_HEAD_SIZE) {
            printf("don't know the size of cached packet, have to read more\n");
            //not enough of packet read to determine size
            *bufp = recv_finish_packet(sock, buffer);
        } else {
            //we can read the size, see if we have the whole packet already
            pack_size = packet_size(buffer->next_boundary);
            printf("cached packet has size %zu bytes\n", pack_size);


            if ((uint32_t)(buffer->buf_end - buffer->next_boundary) < pack_size) {
                printf("but we only have %d read. reading more\n", (buffer->buf_end - buffer->next_boundary));
                // didn't receive enough to match packet size, ask for more
                *bufp = recv_finish_packet(sock,buffer);
            } else {
                printf("cached packet is fully downloaded already.\n");
                //it is fully downloaded already
                *bufp = buffer->next_boundary; //point to the start of it
                buffer->next_boundary += pack_size; // point to the following packet

                // if there *is* no following packet already downloaded, mark everything clean
                if (buffer->next_boundary >= buffer->buf_end) {
                    printf("no cached packets after this, resetting end and boundary\n");
                    buffer->buf_end = buffer->buf;
                    buffer->next_boundary = NULL;
                }

            }
        }

    } else {
        printf("no cached packets, reading new ones\n");
        //no packets in the buffer, wait for more
        *bufp = recv_new_packet(sock, buffer);
    }

    if (*bufp == NULL) {
        return 0; //client disconnected, or fatal error happened.
    }

    pack_size = packet_size(*bufp);
    *bufp += PACK_HEAD_SIZE;

    printf("returning packet at %p with size %zu (%zu with header)\n", *bufp, (pack_size - PACK_HEAD_SIZE ),pack_size);

    return pack_size - PACK_HEAD_SIZE;
}
Ejemplo n.º 14
0
Archivo: net.c Proyecto: pzl/piwm
static char *recv_new_packet(int sock, Buffer *buffer) {
    uint32_t pack_size;
    ssize_t n_recvd;

    printf("starting recv_new_packet, resetting read ptr to %p\n", buffer->buf);

    buffer->buf_end = buffer->buf; //reset "read up to here" pointer

    while ( (n_recvd = recv(sock, buffer->buf_end, (BUF_ALLOC_SIZE - (buffer->buf_end - buffer->buf)), 0)) > 0) {
        /*printf("<");
        for (int i=0; i<n_recvd; i++){
        	printf("[%02X]", buffer->buf_end[i]);
        }
        printf(">\n");*/

        buffer->buf_end += n_recvd;
        printf("read %zu raw bytes, moving read ptr to %p\n", n_recvd, buffer->buf_end);



        //check for oversized packets
        if ((buffer->buf_end - buffer->buf) >= BUF_ALLOC_SIZE) {
            fprintf(stderr, "packet is larger than buffer!\n");
            return NULL;
        }

        //didn't even get full SIZE header, ask for more
        if ( buffer->buf_end - buffer->buf < PACK_HEAD_SIZE) {
            printf("wasn't enough to get header, repeating read\n");
            continue;
        }

        //get the final packet size
        pack_size = packet_size(buffer->buf);
        printf("packet size header read as %zu\n", pack_size);

        //have we read enough to encompass the packet?
        if ( (uint32_t)(buffer->buf_end - buffer->buf) < pack_size) {
            printf("total read (%d) less than packet size (%zu). repeating read\n",(buffer->buf_end - buffer->buf),pack_size);
            continue; //not enough yet
        } else {
            printf("read enough for the packet. breaking read loop\n");
            break; //got it!
        }

    }
    if (n_recvd == 0) {
        fprintf(stderr, "client disconnect\n");
        return NULL;
    } else if (n_recvd < 0) {
        perror("recv (new packet)");
        return NULL;
    }


    if ((uint32_t)(buffer->buf_end - buffer->buf) < pack_size) {
        printf("packet under sized. freaking out\n");
        return NULL; //we never got the whole packet, and didn't catch it above. SHUT IT DOWN
    } else if ((uint32_t)(buffer->buf_end - buffer->buf) > pack_size) {
        printf("read more than one packet. Read: %d, packet is only %zu\n", (buffer->buf_end - buffer->buf),pack_size);
        buffer->next_boundary = buffer->buf + pack_size;  //we started reading something else!
    } else {
        printf("read exactly packet length. resetting buf_end and boundary pointers\n");
        //we matched packet length exactly. Next packet can start at buf start
        buffer->buf_end = buffer->buf;
        buffer->next_boundary = NULL;
    }

    //since this is a new packet, it should be placed at the start of the buffer
    return buffer->buf;
}
Ejemplo n.º 15
0
Archivo: hooks.c Proyecto: op5/merlin
static int send_generic(merlin_event *pkt, void *data)
{
	int result = 0;
	uint i, ntable_stop = num_masters + num_peers;
	linked_item *li;

	if ((!num_nodes || pkt->hdr.code == MAGIC_NONET) && !daemon_wants(pkt->hdr.type)) {
		ldebug("ipcfilter: Not sending %s event. %s, and daemon doesn't want it",
			   callback_name(pkt->hdr.type),
			   pkt->hdr.code == MAGIC_NONET ? "No-net magic" : "No nodes");
		return 0;
	}
	if (!pkt->hdr.code == MAGIC_NONET && !daemon_wants(pkt->hdr.type)) {
		ldebug("ipcfilter: Not sending %s event. No-net magic and daemon doesn't want it",
			   callback_name(pkt->hdr.type));
		return 0;
	}

	pkt->hdr.len = merlin_encode_event(pkt, data);
	if (!pkt->hdr.len) {
		lerr("Header len is 0 for callback %d. Update offset in hookinfo.h", pkt->hdr.type);
		return -1;
	}

	if (is_dupe(pkt)) {
		ldebug("ipcfilter: Not sending %s event: Duplicate packet",
		       callback_name(pkt->hdr.type));
		return 0;
	}

	if (daemon_wants(pkt->hdr.type)) {
		result = ipc_send_event(pkt);
		/*
		 * preserve the event so we can check for dupes,
		 * but only if we successfully sent it
		 */
		if (result < 0)
			memset(&last_pkt, 0, sizeof(last_pkt));
		else
			memcpy(&last_pkt, pkt, packet_size(pkt));
	}

	if (!num_nodes)
		return 0;
	if (pkt->hdr.code == MAGIC_NONET)
		return 0;

	/*
	 * The module can mark certain packets with a magic destination.
	 * Such packets avoid all other inspection and get sent to where
	 * the module wants us to.
	 */
	if (magic_destination(pkt)) {
		if ((pkt->hdr.selection & DEST_MASTERS) == DEST_MASTERS) {
			for (i = 0; i < num_masters; i++) {
				net_sendto(node_table[i], pkt);
			}
		}
		if ((pkt->hdr.selection & DEST_PEERS) == DEST_PEERS) {
			for (i = 0; i < num_peers; i++) {
				net_sendto(peer_table[i], pkt);
			}
		}
		if ((pkt->hdr.selection & DEST_POLLERS) == DEST_POLLERS) {
			for (i = 0; i < num_pollers; i++) {
				net_sendto(poller_table[i], pkt);
			}
		}

		return 0;
	}

	/*
	 * "normal" packets get sent to all peers and masters, and possibly
	 * a group of, or all, pollers as well
	 */

	/* general control packets are for everyone */
	if (pkt->hdr.selection == CTRL_GENERIC && pkt->hdr.type == CTRL_PACKET) {
		ntable_stop = num_nodes;
	}

	/* Send this to all who should have it */
	for (i = 0; i < ntable_stop; i++) {
		net_sendto(node_table[i], pkt);
	}

	/* if we've already sent to everyone we return early */
	if (ntable_stop == num_nodes || !num_pollers)
		return 0;

	li = nodes_by_sel_id(pkt->hdr.selection);
	if (!li) {
		lerr("No matching selection for id %d", pkt->hdr.selection);
		return -1;
	}

	for (; li; li = li->next_item) {
		net_sendto((merlin_node *)li->item, pkt);
	}

	return result;
}
Ejemplo n.º 16
0
Archivo: node.c Proyecto: ageric/merlin
int node_send_binlog(merlin_node *node, merlin_event *pkt)
{
	merlin_event *temp_pkt;
	uint len;

	ldebug("Emptying backlog for %s", node->name);
	while (io_write_ok(node->sock, 10) && !binlog_read(node->binlog, (void **)&temp_pkt, &len)) {
		int result;
		if (!temp_pkt || packet_size(temp_pkt) != (int)len ||
		    !len || !packet_size(temp_pkt) || packet_size(temp_pkt) > MAX_PKT_SIZE)
		{
			if (!temp_pkt) {
				lerr("BACKLOG: binlog returned 0 but presented no data");
			} else {
				lerr("BACKLOG: binlog returned a packet claiming to be of size %d", packet_size(temp_pkt));
			}
			lerr("BACKLOG: binlog claims the data length is %u", len);
			lerr("BACKLOG: wiping backlog. %s is now out of sync", node->name);
			binlog_wipe(node->binlog, BINLOG_UNLINK);
			return -1;
		}
		errno = 0;
		result = node_send(node, temp_pkt, packet_size(temp_pkt), MSG_DONTWAIT);

		/* keep going while we successfully send something */
		if (result == packet_size(temp_pkt)) {
			node->stats.events.sent++;
			node->stats.events.logged--;
			node->stats.bytes.logged -= packet_size(temp_pkt);

			/*
			 * binlog duplicates the memory, so we must release it
			 * when we've sent and counted it
			 */
			free(temp_pkt);
			continue;
		}

		/*
		 * we can recover from total failures by unread()'ing
		 * the entry we just read and then adding the new entry
		 * to the binlog in the hopes that we'll get a
		 * connection up and running again before it's time to
		 * send more data to this node
		 */
		if (result <= 0) {
			if (!binlog_unread(node->binlog, temp_pkt, len)) {
				if (pkt)
					return node_binlog_add(node, pkt);
				return 0;
			} else {
				free(temp_pkt);
			}
		}

		/*
		 * we wrote a partial event or failed to unread the event,
		 * so this node is now out of sync. We must wipe the binlog
		 * and possibly mark this node as being out of sync.
		 */
		lerr("Wiping binlog for %s node %s", node_type(node), node->name);
		binlog_wipe(node->binlog, BINLOG_UNLINK);
		if (pkt) {
			node->stats.events.dropped += node->stats.events.logged + 1;
			node->stats.bytes.dropped += node->stats.bytes.logged + packet_size(pkt);
		}
		node_log_event_count(node, 0);
		return -1;
	}

	return 0;
}