mirror of https://github.com/zlatinb/muwire
core-side changes to enable avatars in chat
parent
9fbf6d1b5d
commit
a0ac1cd3f4
|
@ -414,7 +414,7 @@ public class Core {
|
|||
eventBus.register(UIFetchCertificatesEvent.class, certificateClient)
|
||||
|
||||
log.info("initializing chat server")
|
||||
chatServer = new ChatServer(eventBus, props, trustService, me, spk)
|
||||
chatServer = new ChatServer(eventBus, props, trustService, me, profileSupplier, spk)
|
||||
eventBus.with {
|
||||
register(ChatMessageEvent.class, chatServer)
|
||||
register(ChatDisconnectionEvent.class, chatServer)
|
||||
|
@ -445,7 +445,7 @@ public class Core {
|
|||
eventBus.register(ResultsEvent.class, searchManager)
|
||||
|
||||
log.info("initializing chat manager")
|
||||
chatManager = new ChatManager(eventBus, me, i2pConnector, trustService, props)
|
||||
chatManager = new ChatManager(eventBus, me, profileSupplier, i2pConnector, trustService, props)
|
||||
eventBus.with {
|
||||
register(UIConnectChatEvent.class, chatManager)
|
||||
register(UIDisconnectChatEvent.class, chatManager)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.muwire.core.chat
|
||||
|
||||
import com.muwire.core.profile.MWProfile
|
||||
import com.muwire.core.profile.MWProfileHeader
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
|
@ -15,6 +18,8 @@ import com.muwire.core.util.DataUtil
|
|||
|
||||
import groovy.util.logging.Log
|
||||
|
||||
import java.util.function.Supplier
|
||||
|
||||
@Log
|
||||
class ChatClient implements Closeable {
|
||||
|
||||
|
@ -25,6 +30,7 @@ class ChatClient implements Closeable {
|
|||
private final I2PConnector connector
|
||||
private final EventBus eventBus
|
||||
private final Persona host, me
|
||||
private final Supplier<MWProfile> profileSupplier
|
||||
private final TrustService trustService
|
||||
private final MuWireSettings settings
|
||||
|
||||
|
@ -33,12 +39,15 @@ class ChatClient implements Closeable {
|
|||
private long lastRejectionTime
|
||||
private Thread connectThread
|
||||
|
||||
ChatClient(I2PConnector connector, EventBus eventBus, Persona host, Persona me, TrustService trustService,
|
||||
ChatClient(I2PConnector connector, EventBus eventBus,
|
||||
Persona host, Persona me, Supplier<MWProfile> profileSupplier,
|
||||
TrustService trustService,
|
||||
MuWireSettings settings) {
|
||||
this.connector = connector
|
||||
this.eventBus = eventBus
|
||||
this.host = host
|
||||
this.me = me
|
||||
this.profileSupplier = profileSupplier
|
||||
this.trustService = trustService
|
||||
this.settings = settings
|
||||
}
|
||||
|
@ -67,6 +76,9 @@ class ChatClient implements Closeable {
|
|||
write("IRC\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
write("Version:${Constants.CHAT_VERSION}\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
write("Persona:${me.toBase64()}\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
MWProfile profile = profileSupplier.get()
|
||||
if (profile != null)
|
||||
write("ProfileHeader:${profile.getHeader().toBase64()}\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
write("\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
flush()
|
||||
}
|
||||
|
@ -102,8 +114,8 @@ class ChatClient implements Closeable {
|
|||
synchronized(this) {
|
||||
if (!connectInProgress)
|
||||
return
|
||||
connection = new ChatConnection(eventBus, endpoint, host, false,
|
||||
trustService, settings, Constants.CHAT_VERSION)
|
||||
connection = new ChatConnection(eventBus, endpoint, host, profileSupplier.get()?.getHeader(),
|
||||
false, trustService, settings, Constants.CHAT_VERSION)
|
||||
connection.start()
|
||||
}
|
||||
eventBus.publish(new ChatConnectionEvent(status : ChatConnectionAttemptStatus.SUCCESSFUL, persona : host,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.muwire.core.chat
|
||||
|
||||
import com.muwire.core.profile.MWProfileHeader
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.concurrent.BlockingQueue
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
@ -31,6 +33,7 @@ class ChatConnection implements ChatLink {
|
|||
private final EventBus eventBus
|
||||
private final Endpoint endpoint
|
||||
private final Persona persona
|
||||
private final MWProfileHeader profileHeader
|
||||
private final boolean incoming
|
||||
private final TrustService trustService
|
||||
private final MuWireSettings settings
|
||||
|
@ -49,11 +52,12 @@ class ChatConnection implements ChatLink {
|
|||
|
||||
private volatile long lastPingSentTime
|
||||
|
||||
ChatConnection(EventBus eventBus, Endpoint endpoint, Persona persona, boolean incoming,
|
||||
TrustService trustService, MuWireSettings settings, int version) {
|
||||
ChatConnection(EventBus eventBus, Endpoint endpoint, Persona persona, MWProfileHeader profileHeader,
|
||||
boolean incoming, TrustService trustService, MuWireSettings settings, int version) {
|
||||
this.eventBus = eventBus
|
||||
this.endpoint = endpoint
|
||||
this.persona = persona
|
||||
this.profileHeader = profileHeader
|
||||
this.incoming = incoming
|
||||
this.trustService = trustService
|
||||
this.settings = settings
|
||||
|
@ -90,6 +94,11 @@ class ChatConnection implements ChatLink {
|
|||
persona
|
||||
}
|
||||
|
||||
@Override
|
||||
public MWProfileHeader getProfileHeader() {
|
||||
profileHeader
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (!running.compareAndSet(true, false)) {
|
||||
|
@ -211,7 +220,7 @@ class ChatConnection implements ChatLink {
|
|||
return
|
||||
}
|
||||
def event = new ChatMessageEvent( uuid : uuid, payload : payload, sender : sender,
|
||||
host : host, room : room, chatTime : chatTime, sig : sig)
|
||||
host : host, link: this, room : room, chatTime : chatTime, sig : sig)
|
||||
eventBus.publish(event)
|
||||
if (!incoming)
|
||||
incomingEvents.put(event)
|
||||
|
|
|
@ -3,9 +3,11 @@ package com.muwire.core.chat;
|
|||
import java.io.Closeable;
|
||||
|
||||
import com.muwire.core.Persona;
|
||||
import com.muwire.core.profile.MWProfileHeader;
|
||||
|
||||
public interface ChatLink extends Closeable {
|
||||
public Persona getPersona();
|
||||
public MWProfileHeader getProfileHeader();
|
||||
public boolean isUp();
|
||||
public void sendChat(ChatMessageEvent e);
|
||||
public void sendLeave(Persona p);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.muwire.core.chat
|
||||
|
||||
import com.muwire.core.profile.MWProfile
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
import com.muwire.core.EventBus
|
||||
|
@ -8,19 +10,23 @@ import com.muwire.core.Persona
|
|||
import com.muwire.core.connection.I2PConnector
|
||||
import com.muwire.core.trust.TrustService
|
||||
|
||||
import java.util.function.Supplier
|
||||
|
||||
class ChatManager {
|
||||
private final EventBus eventBus
|
||||
private final Persona me
|
||||
private final I2PConnector connector
|
||||
private final TrustService trustService
|
||||
private final MuWireSettings settings
|
||||
private final Supplier<MWProfile> profileSupplier
|
||||
|
||||
private final Map<Persona, ChatClient> clients = new ConcurrentHashMap<>()
|
||||
|
||||
ChatManager(EventBus eventBus, Persona me, I2PConnector connector, TrustService trustService,
|
||||
MuWireSettings settings) {
|
||||
ChatManager(EventBus eventBus, Persona me, Supplier<MWProfile> profileSupplier,
|
||||
I2PConnector connector, TrustService trustService, MuWireSettings settings) {
|
||||
this.eventBus = eventBus
|
||||
this.me = me
|
||||
this.profileSupplier = profileSupplier
|
||||
this.connector = connector
|
||||
this.trustService = trustService
|
||||
this.settings = settings
|
||||
|
|
|
@ -7,6 +7,7 @@ class ChatMessageEvent extends Event {
|
|||
UUID uuid
|
||||
String payload
|
||||
Persona sender, host
|
||||
ChatLink link
|
||||
String room
|
||||
long chatTime
|
||||
byte [] sig
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
package com.muwire.core.chat
|
||||
|
||||
import com.muwire.core.profile.MWProfile
|
||||
import com.muwire.core.profile.MWProfileHeader
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.function.Predicate
|
||||
import java.util.function.Supplier
|
||||
import java.util.logging.Level
|
||||
import java.util.stream.Collectors
|
||||
|
||||
|
@ -31,6 +36,7 @@ class ChatServer {
|
|||
private final MuWireSettings settings
|
||||
private final TrustService trustService
|
||||
private final Persona me
|
||||
private final Supplier<MWProfile> profileSupplier
|
||||
private final SigningPrivateKey spk
|
||||
|
||||
private final Map<Destination, ChatLink> connections = new ConcurrentHashMap()
|
||||
|
@ -40,11 +46,13 @@ class ChatServer {
|
|||
|
||||
private final AtomicBoolean running = new AtomicBoolean()
|
||||
|
||||
ChatServer(EventBus eventBus, MuWireSettings settings, TrustService trustService, Persona me, SigningPrivateKey spk) {
|
||||
ChatServer(EventBus eventBus, MuWireSettings settings, TrustService trustService,
|
||||
Persona me, Supplier<MWProfile> profileSupplier, SigningPrivateKey spk) {
|
||||
this.eventBus = eventBus
|
||||
this.settings = settings
|
||||
this.trustService = trustService
|
||||
this.me = me
|
||||
this.profileSupplier = profileSupplier
|
||||
this.spk = spk
|
||||
|
||||
Timer timer = new Timer("chat-server-pinger", true)
|
||||
|
@ -96,6 +104,14 @@ class ChatServer {
|
|||
Persona client = new Persona(new ByteArrayInputStream(Base64.decode(headers['Persona'])))
|
||||
if (client.destination != endpoint.destination)
|
||||
throw new Exception("Client destination mismatch")
|
||||
|
||||
MWProfileHeader profileHeader = null
|
||||
if (headers.containsKey("ProfileHeader")) {
|
||||
byte [] decoded = Base64.decode(headers['ProfileHeader'])
|
||||
profileHeader = new MWProfileHeader(new ByteArrayInputStream(decoded))
|
||||
if (profileHeader.getPersona() != client)
|
||||
throw new Exception("profile and persona mismatch")
|
||||
}
|
||||
|
||||
if (!running.get()) {
|
||||
os.write("400 Chat Not Enabled\r\n\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
|
@ -128,7 +144,7 @@ class ChatServer {
|
|||
flush()
|
||||
}
|
||||
|
||||
ChatConnection connection = new ChatConnection(eventBus, endpoint, client, true,
|
||||
ChatConnection connection = new ChatConnection(eventBus, endpoint, client, profileHeader, true,
|
||||
trustService, settings, version)
|
||||
connections.put(endpoint.destination, connection)
|
||||
joinRoom(client, CONSOLE)
|
||||
|
@ -244,11 +260,24 @@ class ChatServer {
|
|||
|
||||
private void processJoin(String room, ChatMessageEvent e) {
|
||||
joinRoom(e.sender, room)
|
||||
|
||||
// tell everyone in the room about this person has joined
|
||||
MWProfileHeader header = getHeaderFromConnection(e.link)
|
||||
|
||||
ChatMessageEvent profileBroadcast = null
|
||||
if (header != null)
|
||||
profileBroadcast = buildProfileBroadcast(header, room)
|
||||
|
||||
rooms[room].each {
|
||||
if (it == e.sender)
|
||||
return
|
||||
connections[it.destination].sendChat(e)
|
||||
if (profileBroadcast != null)
|
||||
connections[it.destination].sendChat(profileBroadcast)
|
||||
}
|
||||
|
||||
|
||||
// tell the new joiner who else is in the room
|
||||
String payload = rooms[room].stream().filter({it != e.sender}).map({it.toBase64()})
|
||||
.collect(Collectors.joining(","))
|
||||
if (payload.length() == 0) {
|
||||
|
@ -262,12 +291,46 @@ class ChatServer {
|
|||
uuid : uuid,
|
||||
payload : payload,
|
||||
sender : me,
|
||||
host : me,
|
||||
host : me,
|
||||
link: LocalChatLink.INSTANCE,
|
||||
room : room,
|
||||
chatTime : now,
|
||||
sig : sig
|
||||
)
|
||||
connections[e.sender.destination].sendChat(echo)
|
||||
|
||||
// send all profiles of people already joined
|
||||
rooms[room].stream().
|
||||
map({connections.get(it.destination)}).
|
||||
map({getHeaderFromConnection(it)}).
|
||||
filter({it != null}).
|
||||
forEach {
|
||||
profileBroadcast = buildProfileBroadcast(it, room)
|
||||
connections[e.sender.destination].sendChat(profileBroadcast)
|
||||
}
|
||||
}
|
||||
|
||||
private MWProfileHeader getHeaderFromConnection(ChatLink link) {
|
||||
if (link instanceof LocalChatLink)
|
||||
return profileSupplier.get()?.getHeader()
|
||||
return link.getProfileHeader()
|
||||
}
|
||||
|
||||
private ChatMessageEvent buildProfileBroadcast(MWProfileHeader header, String room) {
|
||||
UUID uuid = UUID.randomUUID()
|
||||
long now = System.currentTimeMillis()
|
||||
String payload = "/PROFILE ${header.toBase64()}"
|
||||
byte [] sig = ChatConnection.sign(uuid, now, room, payload, me, me, spk)
|
||||
new ChatMessageEvent(
|
||||
uuid: uuid,
|
||||
payload: payload,
|
||||
sender: me,
|
||||
host: me,
|
||||
link: LocalChatLink.INSTANCE,
|
||||
room: room,
|
||||
chatTime: now,
|
||||
sig: sig
|
||||
)
|
||||
}
|
||||
|
||||
private void processLeave(ChatMessageEvent e) {
|
||||
|
@ -330,7 +393,8 @@ class ChatServer {
|
|||
uuid : uuid,
|
||||
payload : payload,
|
||||
sender : me,
|
||||
host : me,
|
||||
host : me,
|
||||
link : LocalChatLink.INSTANCE,
|
||||
room : room,
|
||||
chatTime : now,
|
||||
sig : sig
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.muwire.core.chat
|
||||
|
||||
import com.muwire.core.profile.MWProfileHeader
|
||||
|
||||
import java.util.concurrent.BlockingQueue
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
||||
|
@ -46,4 +48,8 @@ class LocalChatLink implements ChatLink {
|
|||
public Persona getPersona() {
|
||||
null
|
||||
}
|
||||
|
||||
public MWProfileHeader getProfileHeader() {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.muwire.gui
|
||||
|
||||
import com.muwire.core.chat.LocalChatLink
|
||||
|
||||
import static com.muwire.gui.Translator.trans
|
||||
|
||||
import griffon.core.artifact.GriffonController
|
||||
|
@ -95,7 +97,8 @@ class ChatRoomController {
|
|||
def event = new ChatMessageEvent(uuid : uuid,
|
||||
payload : command.source,
|
||||
sender : model.core.me,
|
||||
host : model.host,
|
||||
host : model.host,
|
||||
link: LocalChatLink.INSTANCE,
|
||||
room : room,
|
||||
chatTime : now,
|
||||
sig : sig)
|
||||
|
@ -172,6 +175,7 @@ class ChatRoomController {
|
|||
payload : "/LEAVE",
|
||||
sender : model.core.me,
|
||||
host : model.host,
|
||||
link : LocalChatLink.INSTANCE,
|
||||
room : model.room,
|
||||
chatTime : now,
|
||||
sig : sig)
|
||||
|
@ -266,6 +270,7 @@ class ChatRoomController {
|
|||
payload : join,
|
||||
sender : model.core.me,
|
||||
host : model.host,
|
||||
link: LocalChatLink.INSTANCE,
|
||||
room : ChatServer.CONSOLE,
|
||||
chatTime : now,
|
||||
sig : sig
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.muwire.gui
|
|||
import com.muwire.core.chat.ChatConnection
|
||||
import com.muwire.core.chat.ChatMessageEvent
|
||||
import com.muwire.core.chat.ChatServer
|
||||
import com.muwire.core.chat.LocalChatLink
|
||||
import griffon.core.GriffonApplication
|
||||
import griffon.core.artifact.GriffonController
|
||||
import griffon.core.controller.ControllerAction
|
||||
|
@ -39,6 +40,7 @@ class ChatServerController {
|
|||
payload: command,
|
||||
sender: model.core.me,
|
||||
host: model.host,
|
||||
link: LocalChatLink.INSTANCE,
|
||||
room: ChatServer.CONSOLE,
|
||||
chatTime: now,
|
||||
sig: sig)
|
||||
|
|
Loading…
Reference in New Issue