From cf033dc29da1812402a1e9d53ebaad138c36beeb Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 21 Sep 2018 14:53:35 -0300 Subject: [PATCH] briar-headless: Address second round of review comments --- briar-headless/README.md | 2 +- .../briar/headless/BriarService.kt | 4 +- .../briar/headless/HeadlessModule.kt | 22 ++++---- .../org/briarproject/briar/headless/Router.kt | 14 +++-- .../briar/headless/blogs/BlogController.kt | 46 ++--------------- .../headless/blogs/BlogControllerImpl.kt | 51 +++++++++++++++++++ .../headless/blogs/HeadlessBlogModule.kt | 16 ++++++ .../headless/contact/ContactController.kt | 16 +----- .../headless/contact/ContactControllerImpl.kt | 21 ++++++++ .../headless/contact/HeadlessContactModule.kt | 16 ++++++ .../headless/event/HeadlessEventModule.kt | 16 ++++++ .../headless/event/WebSocketController.kt | 6 +++ .../headless/event/WebSocketControllerImpl.kt | 12 +++-- .../briar/headless/forums/ForumController.kt | 25 ++------- .../headless/forums/ForumControllerImpl.kt | 30 +++++++++++ .../headless/forums/HeadlessForumModule.kt | 16 ++++++ ...ngModule.kt => HeadlessMessagingModule.kt} | 2 +- .../messaging/MessagingControllerImpl.kt | 11 ++-- .../messaging/OutputPrivateMessage.kt | 2 +- .../headless/blogs/BlogControllerTest.kt | 2 +- .../headless/contact/ContactControllerTest.kt | 2 +- .../headless/event/WebSocketControllerTest.kt | 38 ++++++++++++-- .../headless/forums/ForumControllerTest.kt | 10 ++-- .../messaging/MessagingControllerImplTest.kt | 8 +-- 24 files changed, 261 insertions(+), 127 deletions(-) create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/HeadlessBlogModule.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/HeadlessContactModule.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/event/HeadlessEventModule.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/HeadlessForumModule.kt rename briar-headless/src/main/java/org/briarproject/briar/headless/messaging/{MessagingModule.kt => HeadlessMessagingModule.kt} (93%) diff --git a/briar-headless/README.md b/briar-headless/README.md index 4520ffcd5..733eb40be 100644 --- a/briar-headless/README.md +++ b/briar-headless/README.md @@ -101,7 +101,7 @@ Attention: There can messages of other `type`s where the message `body` is `null `POST /messages/{contactId}` -The text of the message should be included in the form parameter `message`. +The text of the message should be included in the form parameter `text`. ### Listing blog posts diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt index ce9b53c04..40e76af33 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.kt @@ -15,8 +15,8 @@ import javax.inject.Singleton @Immutable @Singleton -internal class BriarService @Inject -constructor( +internal class BriarService +@Inject constructor( private val accountManager: AccountManager, private val lifecycleManager: LifecycleManager, private val passwordStrengthEstimator: PasswordStrengthEstimator diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt index 83b3e8f4a..d51ca2c36 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt @@ -24,9 +24,11 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider import org.briarproject.bramble.plugin.tor.LinuxTorPluginFactory import org.briarproject.bramble.system.JavaSystemModule import org.briarproject.bramble.util.StringUtils.fromHexString -import org.briarproject.briar.headless.event.WebSocketController -import org.briarproject.briar.headless.event.WebSocketControllerImpl -import org.briarproject.briar.headless.messaging.MessagingModule +import org.briarproject.briar.headless.blogs.HeadlessBlogModule +import org.briarproject.briar.headless.contact.HeadlessContactModule +import org.briarproject.briar.headless.event.HeadlessEventModule +import org.briarproject.briar.headless.forums.HeadlessForumModule +import org.briarproject.briar.headless.messaging.HeadlessMessagingModule import java.io.File import java.security.GeneralSecurityException import java.util.Collections.emptyList @@ -39,7 +41,11 @@ import javax.net.SocketFactory JavaNetworkModule::class, JavaSystemModule::class, CircumventionModule::class, - MessagingModule::class + HeadlessBlogModule::class, + HeadlessContactModule::class, + HeadlessEventModule::class, + HeadlessForumModule::class, + HeadlessMessagingModule::class ] ) internal class HeadlessModule(private val appDir: File) { @@ -107,12 +113,4 @@ internal class HeadlessModule(private val appDir: File) { } } - @Provides - @Singleton - internal fun provideWebSocketController( - webSocketController: WebSocketControllerImpl - ): WebSocketController { - return webSocketController - } - } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt index 611021cbc..2914be0b7 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt @@ -12,7 +12,8 @@ import org.briarproject.briar.headless.event.WebSocketController import org.briarproject.briar.headless.forums.ForumController import org.briarproject.briar.headless.messaging.MessagingController import java.lang.Runtime.getRuntime -import java.util.logging.Logger +import java.util.concurrent.atomic.AtomicBoolean +import java.util.logging.Logger.getLogger import javax.annotation.concurrent.Immutable import javax.inject.Inject import javax.inject.Singleton @@ -30,11 +31,12 @@ constructor( private val blogController: BlogController ) { - private val logger: Logger = Logger.getLogger(this.javaClass.name) + private val logger = getLogger(Router::javaClass.name) + private val stopped = AtomicBoolean(false) fun start(authToken: String, port: Int, debug: Boolean) { briarService.start() - getRuntime().addShutdownHook(Thread(Runnable { briarService.stop() })) + getRuntime().addShutdownHook(Thread(Runnable { stop() })) val app = Javalin.create() .port(port) @@ -93,8 +95,10 @@ constructor( } private fun stop() { - briarService.stop() - exitProcess(0) + if (!stopped.getAndSet(true)) { + briarService.stop() + exitProcess(0) + } } } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt index d5696e472..549494b7d 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt @@ -1,51 +1,11 @@ package org.briarproject.briar.headless.blogs -import io.javalin.BadRequestResponse import io.javalin.Context -import org.briarproject.bramble.api.identity.IdentityManager -import org.briarproject.bramble.api.system.Clock -import org.briarproject.bramble.util.StringUtils -import org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH -import org.briarproject.briar.api.blog.BlogManager -import org.briarproject.briar.api.blog.BlogPostFactory -import javax.annotation.concurrent.Immutable -import javax.inject.Inject -import javax.inject.Singleton -@Immutable -@Singleton -class BlogController @Inject -constructor( - private val blogManager: BlogManager, - private val blogPostFactory: BlogPostFactory, - private val identityManager: IdentityManager, - private val clock: Clock -) { +interface BlogController { - fun listPosts(ctx: Context): Context { - val posts = blogManager.blogs.flatMap { blog -> - blogManager.getPostHeaders(blog.id).map { header -> - val body = blogManager.getPostBody(header.id) - header.output(body) - } - }.sortedBy { it.timestampReceived } - return ctx.json(posts) - } + fun listPosts(ctx: Context): Context - fun createPost(ctx: Context): Context { - val text = ctx.formParam("text") - if (text == null || text.isEmpty()) - throw BadRequestResponse("Expecting blog post text") - if (StringUtils.toUtf8(text).size > MAX_BLOG_POST_BODY_LENGTH) - throw BadRequestResponse("Too long blog post text") - - val author = identityManager.localAuthor - val blog = blogManager.getPersonalBlog(author) - val now = clock.currentTimeMillis() - val post = blogPostFactory.createBlogPost(blog.id, now, null, author, text) - blogManager.addLocalPost(post) - val header = blogManager.getPostHeader(blog.id, post.message.id) - return ctx.json(header.output(text)) - } + fun createPost(ctx: Context): Context } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt new file mode 100644 index 000000000..21f8a719d --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogControllerImpl.kt @@ -0,0 +1,51 @@ +package org.briarproject.briar.headless.blogs + +import io.javalin.BadRequestResponse +import io.javalin.Context +import org.briarproject.bramble.api.identity.IdentityManager +import org.briarproject.bramble.api.system.Clock +import org.briarproject.bramble.util.StringUtils +import org.briarproject.briar.api.blog.BlogConstants +import org.briarproject.briar.api.blog.BlogManager +import org.briarproject.briar.api.blog.BlogPostFactory +import javax.annotation.concurrent.Immutable +import javax.inject.Inject +import javax.inject.Singleton + +@Immutable +@Singleton +internal class BlogControllerImpl +@Inject constructor( + private val blogManager: BlogManager, + private val blogPostFactory: BlogPostFactory, + private val identityManager: IdentityManager, + private val clock: Clock +) : BlogController { + + override fun listPosts(ctx: Context): Context { + val posts = blogManager.blogs.flatMap { blog -> + blogManager.getPostHeaders(blog.id).map { header -> + val body = blogManager.getPostBody(header.id) + header.output(body) + } + }.sortedBy { it.timestampReceived } + return ctx.json(posts) + } + + override fun createPost(ctx: Context): Context { + val text = ctx.formParam("text") + if (text == null || text.isEmpty()) + throw BadRequestResponse("Expecting blog post text") + if (StringUtils.utf8IsTooLong(text, BlogConstants.MAX_BLOG_POST_BODY_LENGTH)) + throw BadRequestResponse("Too long blog post text") + + val author = identityManager.localAuthor + val blog = blogManager.getPersonalBlog(author) + val now = clock.currentTimeMillis() + val post = blogPostFactory.createBlogPost(blog.id, now, null, author, text) + blogManager.addLocalPost(post) + val header = blogManager.getPostHeader(blog.id, post.message.id) + return ctx.json(header.output(text)) + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/HeadlessBlogModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/HeadlessBlogModule.kt new file mode 100644 index 000000000..affe44110 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/HeadlessBlogModule.kt @@ -0,0 +1,16 @@ +package org.briarproject.briar.headless.blogs + +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +class HeadlessBlogModule { + + @Provides + @Singleton + internal fun provideBlogController(blogController: BlogControllerImpl): BlogController { + return blogController + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt index 1de72d5c9..9eb21a120 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt @@ -1,21 +1,9 @@ package org.briarproject.briar.headless.contact import io.javalin.Context -import org.briarproject.bramble.api.contact.ContactManager -import javax.annotation.concurrent.Immutable -import javax.inject.Inject -import javax.inject.Singleton -@Immutable -@Singleton -class ContactController @Inject -constructor(private val contactManager: ContactManager) { +interface ContactController { - fun list(ctx: Context): Context { - val contacts = contactManager.activeContacts.map { contact -> - contact.output() - } - return ctx.json(contacts) - } + fun list(ctx: Context): Context } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt new file mode 100644 index 000000000..7a53476a9 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactControllerImpl.kt @@ -0,0 +1,21 @@ +package org.briarproject.briar.headless.contact + +import io.javalin.Context +import org.briarproject.bramble.api.contact.ContactManager +import javax.annotation.concurrent.Immutable +import javax.inject.Inject +import javax.inject.Singleton + +@Immutable +@Singleton +internal class ContactControllerImpl +@Inject constructor(private val contactManager: ContactManager) : ContactController { + + override fun list(ctx: Context): Context { + val contacts = contactManager.activeContacts.map { contact -> + contact.output() + } + return ctx.json(contacts) + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/HeadlessContactModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/HeadlessContactModule.kt new file mode 100644 index 000000000..bf91804b3 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/HeadlessContactModule.kt @@ -0,0 +1,16 @@ +package org.briarproject.briar.headless.contact + +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +class HeadlessContactModule { + + @Provides + @Singleton + internal fun provideContactController(contactController: ContactControllerImpl): ContactController { + return contactController + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/event/HeadlessEventModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/event/HeadlessEventModule.kt new file mode 100644 index 000000000..f540a7fba --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/event/HeadlessEventModule.kt @@ -0,0 +1,16 @@ +package org.briarproject.briar.headless.event + +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +class HeadlessEventModule { + + @Provides + @Singleton + internal fun provideWebSocketController(webSocketController: WebSocketControllerImpl): WebSocketController { + return webSocketController + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt index e7f8c9fd0..ed723d556 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketController.kt @@ -1,11 +1,17 @@ package org.briarproject.briar.headless.event import io.javalin.websocket.WsSession +import org.briarproject.bramble.api.lifecycle.IoExecutor +import javax.annotation.concurrent.ThreadSafe +@ThreadSafe interface WebSocketController { val sessions: MutableSet + /** + * Sends an event to all open sessions using the [IoExecutor]. + */ fun sendEvent(name: String, obj: Any) } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt index c5dc665d8..6ea7bf6e5 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/event/WebSocketControllerImpl.kt @@ -2,26 +2,28 @@ package org.briarproject.briar.headless.event import io.javalin.json.JavalinJson.toJson import io.javalin.websocket.WsSession +import org.briarproject.bramble.api.lifecycle.IoExecutor import org.briarproject.bramble.util.LogUtils.logException import org.eclipse.jetty.websocket.api.WebSocketException import java.io.IOException import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Executor import java.util.logging.Level -import java.util.logging.Logger +import java.util.logging.Logger.getLogger import javax.annotation.concurrent.Immutable import javax.inject.Inject import javax.inject.Singleton @Immutable @Singleton -internal class WebSocketControllerImpl @Inject constructor() : - WebSocketController { +internal class WebSocketControllerImpl +@Inject constructor(@IoExecutor private val ioExecutor: Executor) : WebSocketController { - private val logger: Logger = Logger.getLogger(this.javaClass.name) + private val logger = getLogger(WebSocketControllerImpl::javaClass.name) override val sessions: MutableSet = ConcurrentHashMap.newKeySet() - override fun sendEvent(name: String, obj: Any) { + override fun sendEvent(name: String, obj: Any) = ioExecutor.execute { sessions.forEach { session -> val event = OutputEvent(name, obj) try { diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt index 54fe88ede..8ffd8ee90 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt @@ -1,30 +1,11 @@ package org.briarproject.briar.headless.forums -import io.javalin.BadRequestResponse import io.javalin.Context -import org.briarproject.bramble.util.StringUtils -import org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH -import org.briarproject.briar.api.forum.ForumManager -import javax.annotation.concurrent.Immutable -import javax.inject.Inject -import javax.inject.Singleton -@Immutable -@Singleton -class ForumController @Inject -constructor(private val forumManager: ForumManager) { +interface ForumController { - fun list(ctx: Context): Context { - return ctx.json(forumManager.forums.output()) - } + fun list(ctx: Context): Context - fun create(ctx: Context): Context { - val name = ctx.formParam("name") - if (name == null || name.isNullOrEmpty()) - throw BadRequestResponse("Expecting Forum Name") - if (StringUtils.toUtf8(name).size > MAX_FORUM_NAME_LENGTH) - throw BadRequestResponse("Forum name is too long") - return ctx.json(forumManager.addForum(name).output()) - } + fun create(ctx: Context): Context } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt new file mode 100644 index 000000000..1e0d49d78 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumControllerImpl.kt @@ -0,0 +1,30 @@ +package org.briarproject.briar.headless.forums + +import io.javalin.BadRequestResponse +import io.javalin.Context +import org.briarproject.bramble.util.StringUtils +import org.briarproject.briar.api.forum.ForumConstants +import org.briarproject.briar.api.forum.ForumManager +import javax.annotation.concurrent.Immutable +import javax.inject.Inject +import javax.inject.Singleton + +@Immutable +@Singleton +internal class ForumControllerImpl +@Inject constructor(private val forumManager: ForumManager) : ForumController { + + override fun list(ctx: Context): Context { + return ctx.json(forumManager.forums.output()) + } + + override fun create(ctx: Context): Context { + val name = ctx.formParam("text") + if (name == null || name.isNullOrEmpty()) + throw BadRequestResponse("Expecting Forum Name") + if (StringUtils.utf8IsTooLong(name, ForumConstants.MAX_FORUM_NAME_LENGTH)) + throw BadRequestResponse("Forum name is too long") + return ctx.json(forumManager.addForum(name).output()) + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/HeadlessForumModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/HeadlessForumModule.kt new file mode 100644 index 000000000..5e7b90174 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/HeadlessForumModule.kt @@ -0,0 +1,16 @@ +package org.briarproject.briar.headless.forums + +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +class HeadlessForumModule { + + @Provides + @Singleton + internal fun provideForumController(forumController: ForumControllerImpl): ForumController { + return forumController + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/HeadlessMessagingModule.kt similarity index 93% rename from briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingModule.kt rename to briar-headless/src/main/java/org/briarproject/briar/headless/messaging/HeadlessMessagingModule.kt index a334380f6..31d336a15 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingModule.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/HeadlessMessagingModule.kt @@ -6,7 +6,7 @@ import org.briarproject.bramble.api.event.EventBus import javax.inject.Singleton @Module -class MessagingModule { +class HeadlessMessagingModule { @Provides @Singleton diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt index c1e023e9b..8a6091ce1 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt @@ -11,6 +11,7 @@ import org.briarproject.bramble.api.db.NoSuchContactException import org.briarproject.bramble.api.event.Event import org.briarproject.bramble.api.event.EventListener import org.briarproject.bramble.api.system.Clock +import org.briarproject.bramble.util.StringUtils.utf8IsTooLong import org.briarproject.briar.api.messaging.* import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent @@ -26,8 +27,8 @@ internal const val EVENT_PRIVATE_MESSAGE = @Immutable @Singleton -internal class MessagingControllerImpl @Inject -constructor( +internal class MessagingControllerImpl +@Inject constructor( private val messagingManager: MessagingManager, private val conversationManager: ConversationManager, private val privateMessageFactory: PrivateMessageFactory, @@ -55,10 +56,10 @@ constructor( override fun write(ctx: Context): Context { val contact = getContact(ctx) - val message = ctx.formParam("message") + val message = ctx.formParam("text") if (message == null || message.isEmpty()) throw BadRequestResponse("Expecting Message text") - if (message.length > MAX_PRIVATE_MESSAGE_BODY_LENGTH) + if (utf8IsTooLong(message, MAX_PRIVATE_MESSAGE_BODY_LENGTH)) throw BadRequestResponse("Message text too large") val group = messagingManager.getContactGroup(contact) @@ -71,7 +72,7 @@ constructor( override fun eventOccurred(e: Event) { when (e) { - is PrivateMessageReceivedEvent<*> -> dbExecutor.run { + is PrivateMessageReceivedEvent<*> -> dbExecutor.execute { val body = messagingManager.getMessageBody(e.messageHeader.id) webSocketController.sendEvent(EVENT_PRIVATE_MESSAGE, e.output(body)) } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt index ef8897eeb..b26c53b73 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt @@ -12,7 +12,7 @@ internal abstract class OutputPrivateMessage( open val body: String? ) { - open val type: String get() = throw NotImplementedError() + abstract val type: String val contactId: Int get() = iContactId.int val timestamp: Long get() = iHeader.timestamp val read: Boolean get() = iHeader.isRead diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt index fbd76b697..fa242b882 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt @@ -23,7 +23,7 @@ internal class BlogControllerTest : ControllerTest() { private val blogPostFactory = mockk() private val controller = - BlogController(blogManager, blogPostFactory, identityManager, clock) + BlogControllerImpl(blogManager, blogPostFactory, identityManager, clock) private val blog = Blog(group, author, false) private val parentId: MessageId? = null diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerTest.kt index 76cff5811..c4ffb9531 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/contact/ContactControllerTest.kt @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test internal class ContactControllerTest : ControllerTest() { - private val controller = ContactController(contactManager) + private val controller = ContactControllerImpl(contactManager) @Test fun testEmptyContactList() { diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/event/WebSocketControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/event/WebSocketControllerTest.kt index a3ab33ed9..3cbe0d6b4 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/event/WebSocketControllerTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/event/WebSocketControllerTest.kt @@ -3,17 +3,22 @@ package org.briarproject.briar.headless.event import io.javalin.json.JavalinJson.toJson import io.javalin.websocket.WsSession import io.mockk.* +import org.briarproject.bramble.test.ImmediateExecutor import org.briarproject.briar.api.messaging.PrivateMessageHeader import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent import org.briarproject.briar.headless.ControllerTest import org.briarproject.briar.headless.messaging.EVENT_PRIVATE_MESSAGE import org.briarproject.briar.headless.messaging.output +import org.eclipse.jetty.websocket.api.WebSocketException import org.junit.jupiter.api.Test +import java.io.IOException internal class WebSocketControllerTest : ControllerTest() { - private val session = mockk() - private val controller = WebSocketControllerImpl() + private val session1 = mockk() + private val session2 = mockk() + + private val controller = WebSocketControllerImpl(ImmediateExecutor()) private val header = PrivateMessageHeader(message.id, group.id, timestamp, true, true, true, true) @@ -21,17 +26,40 @@ internal class WebSocketControllerTest : ControllerTest() { private val outputEvent = OutputEvent(EVENT_PRIVATE_MESSAGE, event.output(body)) @Test - fun testSessionSend() { + fun testSendEvent() { val slot = CapturingSlot() - every { session.send(capture(slot)) } just Runs + every { session1.send(capture(slot)) } just Runs - controller.sessions.add(session) + controller.sessions.add(session1) controller.sendEvent(EVENT_PRIVATE_MESSAGE, event.output(body)) assertJsonEquals(slot.captured, outputEvent) } + @Test + fun testSendEventIOException() { + testSendEventException(IOException()) + } + + @Test + fun testSendEventWebSocketException() { + testSendEventException(WebSocketException()) + } + + private fun testSendEventException(throwable: Throwable) { + val slot = CapturingSlot() + + every { session1.send(capture(slot)) } throws throwable + every { session2.send(capture(slot)) } just Runs + + controller.sessions.add(session1) + controller.sessions.add(session2) + controller.sendEvent(EVENT_PRIVATE_MESSAGE, event.output(body)) + + verify { session2.send(slot.captured) } + } + @Test fun testOutputPrivateMessageReceivedEvent() { val json = """ diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/forums/ForumControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/forums/ForumControllerTest.kt index f7ac8a89e..e413e9d96 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/forums/ForumControllerTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/forums/ForumControllerTest.kt @@ -16,7 +16,7 @@ internal class ForumControllerTest : ControllerTest() { private val forumManager = mockk() - private val controller = ForumController(forumManager) + private val controller = ForumControllerImpl(forumManager) private val forum = Forum(group, getRandomString(5), getRandomBytes(5)) @@ -30,7 +30,7 @@ internal class ForumControllerTest : ControllerTest() { @Test fun create() { - every { ctx.formParam("name") } returns forum.name + every { ctx.formParam("text") } returns forum.name every { forumManager.addForum(forum.name) } returns forum every { ctx.json(forum.output()) } returns ctx @@ -39,21 +39,21 @@ internal class ForumControllerTest : ControllerTest() { @Test fun createNoName() { - every { ctx.formParam("name") } returns null + every { ctx.formParam("text") } returns null assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } } @Test fun createEmptyName() { - every { ctx.formParam("name") } returns "" + every { ctx.formParam("text") } returns "" assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } } @Test fun createTooLongName() { - every { ctx.formParam("name") } returns getRandomString(MAX_FORUM_NAME_LENGTH + 1) + every { ctx.formParam("text") } returns getRandomString(MAX_FORUM_NAME_LENGTH + 1) assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } } diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt index 891baaa7b..2dc197b6d 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt @@ -76,7 +76,7 @@ internal class MessagingControllerImplTest : ControllerTest() { val slot = CapturingSlot() expectGetContact() - every { ctx.formParam("message") } returns body + every { ctx.formParam("text") } returns body every { messagingManager.getContactGroup(contact) } returns group every { clock.currentTimeMillis() } returns timestamp every { @@ -110,7 +110,7 @@ internal class MessagingControllerImplTest : ControllerTest() { @Test fun writeNonexistentBody() { expectGetContact() - every { ctx.formParam("message") } returns null + every { ctx.formParam("text") } returns null assertThrows(BadRequestResponse::class.java) { controller.write(ctx) } } @@ -118,7 +118,7 @@ internal class MessagingControllerImplTest : ControllerTest() { @Test fun writeEmptyBody() { expectGetContact() - every { ctx.formParam("message") } returns "" + every { ctx.formParam("text") } returns "" assertThrows(BadRequestResponse::class.java) { controller.write(ctx) } } @@ -126,7 +126,7 @@ internal class MessagingControllerImplTest : ControllerTest() { @Test fun writeTooLongBody() { expectGetContact() - every { ctx.formParam("message") } returns getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1) + every { ctx.formParam("text") } returns getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1) assertThrows(BadRequestResponse::class.java) { controller.write(ctx) } }