XMPP 错误的发件人地址(广播服务器端)
XMPP wrong sender address (broadcast serverside)
从服务器向一个用户的所有活动客户端发送消息时,发件人地址写入不正确。
这是广播功能(服务器端):
private void sendAllSessions(final StringBuilder message, final Entity sender,
final ServerRuntimeContext serverContext, EMailAddress to) {
EntityImpl recipient = new EntityImpl(to.getLocalName().getLocalName(), to.getDomain().getDomainName(), null);
Stanza build = createStanza(message, sender, recipient);
for (SessionContext sessionContext : serverContext.getResourceRegistry().getSessions(recipient)) {
SessionState state = sessionContext.getState();
SessionStateHolder stateHolder = new SessionStateHolder();
stateHolder.setState(state);
Stanza stanza = new MessageStanza(build);
LOG.severe("Send xmpp stanza: " + stanza + " from " + stanza.getFrom());
serverContext.getStanzaProcessor().processStanza(serverContext, sessionContext, stanza, stateHolder);
}
}
private Stanza createStanza(final StringBuilder strb, final Entity sender, final EntityImpl recipient) {
try {
LOG.severe("Create xmpp stanza from " + sender + " (" + sender.getFullQualifiedName() + ") to recipient "
+ recipient + " (" + recipient.getFullQualifiedName() + ")!");
StanzaBuilder sb = StanzaBuilder.createMessageStanza(sender, recipient, MessageStanzaType.HEADLINE, "html",
strb.toString());
Stanza build = sb.build();
return build;
} catch (RuntimeException e) {
StanzaBuilder sb = StanzaBuilder.createMessageStanza(sender, recipient, MessageStanzaType.NORMAL, null,
strb.toString());
Stanza build = sb.build();
return build;
}
}
这是日志记录(服务器端):
07-Oct-2021 12:43:58.220 SEVERE [http-nio-80-exec-147] xx.DefaultChat.createStanza Create xmpp stanza from release-ma@example.com (release-ma@example.com) to recipient admin@example.com (admin@example.com)!
07-Oct-2021 12:43:58.222 SEVERE [http-nio-80-exec-147] xx.DefaultChat.sendAllSessions Send xmpp stanza: message.body.Thanks, please wait... from release-ma@example.com
07-Oct-2021 12:43:58.229 FINE [NioProcessor-2] org.apache.vysper.mina.StanzaLoggingFilter.messageSent ><message xmlns="jabber:client" to="release-ma@example.com" from="example.com" type="error"><body>Thanks, please wait...</body><error type="modify"><unknown-sender xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"></unknown-sender></error></message>
人类可读的xml是(从服务器到客户端):
<message xmlns="jabber:client" to="release-ma@example.com"
from="example.com" type="error">
<body>Thanks, please wait...</body>
<error type="modify">
<unknown-sender
xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"></unknown-sender>
</error>
</message>
我的问题是为什么 XML-Stanza 指出发件人(发件人)只是域?
这是服务器的错误回复,因此是服务器发送此消息,而不是特定用户。
If you look at the source code of handling an error:
StanzaBuilder responseBuilder = StanzaBuilder.createDirectReply(stanza, true, "error");
The 2nd parameter is "fromIsServerOnly" parameter:
public static StanzaBuilder createDirectReply(XMPPCoreStanza original, boolean fromIsServerOnly, String type)
And in that case the Stanza which is created strips the from address to be the domain only:
if (fromIsServerOnly)
newFrom = new EntityImpl(null, newFrom.getDomain(), null);
stanzaBuilder.addAttribute("from", newFrom.getFullQualifiedName());
经过一些调试后,我注意到了这一行(在 org.apache.vysper.xmpp.protocol.ProtocolWorker 中):
// make sure that 'from' (if present) matches the bare authorized entity
// else respond with a stanza error 'unknown-sender'
// see rfc3920_draft-saintandre-rfc3920bis-04.txt#8.5.4
if (from != null && sessionContext.getInitiatingEntity() != null) {
Entity fromBare = from.getBareJID();
Entity initiatingEntity = sessionContext.getInitiatingEntity();
if (!initiatingEntity.equals(fromBare)) {
responseWriter.handleWrongFromJID(sessionContext, stanza);
return;
}
}
所以我加了一行:
private void sendAllSessions(final StringBuilder message, final Entity sender,
final ServerRuntimeContext serverContext, final EMailAddress recipientAddress) {
EntityImpl recipient = new EntityImpl(recipientAddress.getLocalName().getLocalName(),
recipientAddress.getDomain().getDomainName(), null);
Stanza build = createStanza(message, sender, recipient);
for (SessionContext sessionContext : serverContext.getResourceRegistry().getSessions(recipient)) {
SessionState state = sessionContext.getState();
SessionStateHolder stateHolder = new SessionStateHolder();
stateHolder.setState(state);
Stanza stanza = new MessageStanza(build);
LOG.severe("Send xmpp stanza: " + stanza + " from " + stanza.getFrom());
sessionContext.setInitiatingEntity(sender); // THIS LINE IS ADDED
serverContext.getStanzaProcessor().processStanza(serverContext, sessionContext, stanza, stateHolder);
}
}
现在效果很好:
<message type="headline" from="xxx" to="xxx" xml:lang="html">
<body>Test</body>
</message>
从服务器向一个用户的所有活动客户端发送消息时,发件人地址写入不正确。
这是广播功能(服务器端):
private void sendAllSessions(final StringBuilder message, final Entity sender,
final ServerRuntimeContext serverContext, EMailAddress to) {
EntityImpl recipient = new EntityImpl(to.getLocalName().getLocalName(), to.getDomain().getDomainName(), null);
Stanza build = createStanza(message, sender, recipient);
for (SessionContext sessionContext : serverContext.getResourceRegistry().getSessions(recipient)) {
SessionState state = sessionContext.getState();
SessionStateHolder stateHolder = new SessionStateHolder();
stateHolder.setState(state);
Stanza stanza = new MessageStanza(build);
LOG.severe("Send xmpp stanza: " + stanza + " from " + stanza.getFrom());
serverContext.getStanzaProcessor().processStanza(serverContext, sessionContext, stanza, stateHolder);
}
}
private Stanza createStanza(final StringBuilder strb, final Entity sender, final EntityImpl recipient) {
try {
LOG.severe("Create xmpp stanza from " + sender + " (" + sender.getFullQualifiedName() + ") to recipient "
+ recipient + " (" + recipient.getFullQualifiedName() + ")!");
StanzaBuilder sb = StanzaBuilder.createMessageStanza(sender, recipient, MessageStanzaType.HEADLINE, "html",
strb.toString());
Stanza build = sb.build();
return build;
} catch (RuntimeException e) {
StanzaBuilder sb = StanzaBuilder.createMessageStanza(sender, recipient, MessageStanzaType.NORMAL, null,
strb.toString());
Stanza build = sb.build();
return build;
}
}
这是日志记录(服务器端):
07-Oct-2021 12:43:58.220 SEVERE [http-nio-80-exec-147] xx.DefaultChat.createStanza Create xmpp stanza from release-ma@example.com (release-ma@example.com) to recipient admin@example.com (admin@example.com)!
07-Oct-2021 12:43:58.222 SEVERE [http-nio-80-exec-147] xx.DefaultChat.sendAllSessions Send xmpp stanza: message.body.Thanks, please wait... from release-ma@example.com
07-Oct-2021 12:43:58.229 FINE [NioProcessor-2] org.apache.vysper.mina.StanzaLoggingFilter.messageSent ><message xmlns="jabber:client" to="release-ma@example.com" from="example.com" type="error"><body>Thanks, please wait...</body><error type="modify"><unknown-sender xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"></unknown-sender></error></message>
人类可读的xml是(从服务器到客户端):
<message xmlns="jabber:client" to="release-ma@example.com"
from="example.com" type="error">
<body>Thanks, please wait...</body>
<error type="modify">
<unknown-sender
xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"></unknown-sender>
</error>
</message>
我的问题是为什么 XML-Stanza 指出发件人(发件人)只是域?
这是服务器的错误回复,因此是服务器发送此消息,而不是特定用户。
If you look at the source code of handling an error:
StanzaBuilder responseBuilder = StanzaBuilder.createDirectReply(stanza, true, "error");
The 2nd parameter is "fromIsServerOnly" parameter:
public static StanzaBuilder createDirectReply(XMPPCoreStanza original, boolean fromIsServerOnly, String type)
And in that case the Stanza which is created strips the from address to be the domain only:
if (fromIsServerOnly)
newFrom = new EntityImpl(null, newFrom.getDomain(), null);
stanzaBuilder.addAttribute("from", newFrom.getFullQualifiedName());
经过一些调试后,我注意到了这一行(在 org.apache.vysper.xmpp.protocol.ProtocolWorker 中):
// make sure that 'from' (if present) matches the bare authorized entity
// else respond with a stanza error 'unknown-sender'
// see rfc3920_draft-saintandre-rfc3920bis-04.txt#8.5.4
if (from != null && sessionContext.getInitiatingEntity() != null) {
Entity fromBare = from.getBareJID();
Entity initiatingEntity = sessionContext.getInitiatingEntity();
if (!initiatingEntity.equals(fromBare)) {
responseWriter.handleWrongFromJID(sessionContext, stanza);
return;
}
}
所以我加了一行:
private void sendAllSessions(final StringBuilder message, final Entity sender,
final ServerRuntimeContext serverContext, final EMailAddress recipientAddress) {
EntityImpl recipient = new EntityImpl(recipientAddress.getLocalName().getLocalName(),
recipientAddress.getDomain().getDomainName(), null);
Stanza build = createStanza(message, sender, recipient);
for (SessionContext sessionContext : serverContext.getResourceRegistry().getSessions(recipient)) {
SessionState state = sessionContext.getState();
SessionStateHolder stateHolder = new SessionStateHolder();
stateHolder.setState(state);
Stanza stanza = new MessageStanza(build);
LOG.severe("Send xmpp stanza: " + stanza + " from " + stanza.getFrom());
sessionContext.setInitiatingEntity(sender); // THIS LINE IS ADDED
serverContext.getStanzaProcessor().processStanza(serverContext, sessionContext, stanza, stateHolder);
}
}
现在效果很好:
<message type="headline" from="xxx" to="xxx" xml:lang="html">
<body>Test</body>
</message>