     (insert "filter:" msg)
     (unless (bolp) (newline)))
   (let* ((json-object-type 'plist)
-         (json-msg (json-read-from-string msg)))
-    (unless (member (plist-get json-msg :ip) *emdocs-client-connections*)
-      (add-to-list '*emdocs-server-clients*
-                   (cons (plist-get json-msg :buffer) sock))
-      (emdocs-connect-client (plist-get json-msg :buffer)
-                             (plist-get json-msg :ip))
+         (json-msg (json-read-from-string msg))
+         (buffer (plist-get json-msg :buffer))
+         (ip (plist-get json-msg :ip)))
+    (unless (find ip *emdocs-outgoing-clients*
+                  :test #'emdocs-is-ip-from-client)
+      (add-to-list '*emdocs-incoming-clients*
+                   (make-instance 'emdocs-client
+                                  :process sock
+                                  :attached-buffer buffer
+                                  :ip ip))
+      (emdocs-connect-client buffer ip)
       (emdocs-broadcast-message msg))))
 
 (defun emdocs-setup-server (my-ip)

                          (buffer-name buffer)
                        buffer)
             :ip ,(emdocs-get-internal-ip-address)))))
        ((string-match "^\{.*\}$" msg)
         (let* ((json-object-type 'plist)
                (json-msg (json-read-from-string msg)))
           (if (plist-get json-msg :ip) ; if being told to connect
               (unless (member (plist-get json-msg :ip)
                               *emdocs-client-connections*)
                 (emdocs-connect-client (plist-get json-msg :buffer)
                                        (plist-get json-msg :ip)))
             (with-current-buffer (plist-get json-msg :buffer)
               (save-excursion
                 (setq emdocs-is-network-insert t)
                 (unwind-protect
                     (cond
                      ((string-equal "insert" (plist-get json-msg :edit_type))
                       (goto-char (plist-get json-msg :point))
                       (insert (plist-get json-msg :content)))
                      ((string-equal "delete" (plist-get json-msg :edit_type))
                       (goto-char (plist-get json-msg :point))
                       (delete-char (plist-get json-msg :content))))
                   (setq emdocs-is-network-insert nil)))))))))

(defun emdocs-connect-client (buffer ip)
  "docstring"
  (unless (string-equal ip (emdocs-get-internal-ip-address))
    (let ((process (make-network-process
                    :name (emdocs-get-client-process-name buffer ip)
                    ;; TODO: remove the log buffer
                    :buffer (emdocs-get-client-process-buffer buffer)

"Invalid ip address. Keep in mind emdocs only works for private ip addresses.")
    (setq emdocs-mode nil)))

(defun emdocs-test-if-client-attached-to-buffer (client)
  (string-equal
   (emdocs-get-attached-buffer client)
   (buffer-name)))

(defun emdocs-disconnect ()
  "docstring"
  ;; (loop for client in emdocs-initial-client
  ;;       do (when (and client
  ;;                     (not (eq client 'no-conn)))
  ;;            (delete-process client)))
  ;; (setq emdocs-initial-client nil)
  ;; (loop for client in *emdocs-server-clients*
  ;;       do (when (string-equal (car client) (buffer-name (current-buffer)))
  ;;            (delete-process (cdr client))))
  ;; (setq *emdocs-server-clients*
  ;;       (remove-if
  ;;        (lambda (item)
  ;;          (string-equal (car item) (buffer-name (current-buffer))))
  ;;        *emdocs-server-clients*))
  ;; (setq-local after-change-functions
  ;;             (remove #'emdocs-after-change-lambda after-change-functions))
  (loop for client in *emdocs-outgoing-clients*
        do (when (emdocs-test-if-client-attached-to-buffer client)
             (delete-process (emdocs-get-process client))))
  (setq *emdocs-outgoing-clients*
        (remove-if #'emdocs-test-if-client-attached-to-buffer
                   *emdocs-outgoing-clients*))
  (loop for client in *emdocs-incoming-clients*
        do (when (emdocs-test-if-client-attached-to-buffer client)
             (delete-process (emdocs-get-process client))))
  (setq *emdocs-incoming-clients*
        (remove-if #'emdocs-test-if-client-attached-to-buffer
                   *emdocs-incoming-clients*)))

;;; interactives
(defun emdocs-kill-server ()
