Message receiveMessageFromSocket (FragmentProcessor fp, ByteArrayOutputStream baos) throws IOException
	{
		baos.reset ();
		
		int currentOpcode = 0;
		
		do {
			fp.readHeader ();
			
			if (!fp.mask)
				throw new IOException ("unmasked fragment");
			
			if (currentOpcode == 0)
			{
				if (fp.opcode != 0)
					currentOpcode = fp.opcode;
				else
					throw new IOException ("first fragment of message is continuation fragment");
				if (isControlOpcode (fp.opcode) && !fp.fin)
					throw new IOException ("fragmented control packet");
			}
			else
			{
				if (fp.opcode != 0)
					throw new IOException ("fragment with opcode after first fragment");
			}
			
			if (fp.payloadLength > maximumPayloadSize)
				throw new IOException ("payload too large (" +
					fp.payloadLength + " > " + maximumPayloadSize +
				")");
			if (baos.size () + fp.payloadLength > maximumMessageSize)
				throw new IOException ("message too large");
			
			fp.readPayload (baos);
		} while (!fp.fin);
		
		return new Message (currentOpcode, baos.toByteArray ());
	}