           nil
         (format-network-address (cdar (network-interface-list)) t)))))
 
-(defun emdocs-server-sentinel (buffer sock msg)
-  "docstring")
+(defun emdocs-get-server-process-buffer ()
+  "docstring"
+  (concat "*emdocs-server-log*"))
 
-(defun emdocs-server-filter (buffer sock msg)
-  "docstring")
+(defun emdocs-get-client-process-buffer (buffer)
+  "docstring"
+  (concat "*emdocs-client-log:" (buffer-name buffer) "*"))
 
-(defun emdocs-setup-server (buffer my-ip)
+(defun emdocs-get-server-process-name ()
+  "docstring"
+  (concat "*emdocs-server*"))
+
+(defun emdocs-get-client-process-name (buffer ip)
+  "docstring"
+  (concat "*emdocs-client:" (buffer-name buffer) ":" ip "*"))
+
+(defun emdocs-server-sentinel (sock msg)
+  "docstring"
+  (with-current-buffer (emdocs-get-server-process-buffer)
+    (goto-char (point-min))
+    (insert "sentinel:" msg)
+    (newline))
+  (cond ((string-match "^open from [0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\n$" msg)
+         (process-send-string sock "give your ip and buffer\n"))))
+
+(defun emdocs-server-filter (sock msg)
+  "docstring"
+  (with-current-buffer (emdocs-get-server-process-buffer)
+    (goto-char (point-min))
+    (insert "filter:" msg)
+    (newline)))
+
+(defun emdocs-setup-server (my-ip)
   "docstring"
   (make-network-process
-   :name (concat "*emdocs-server:" (buffer-name buffer) "*")
+   :name (emdocs-get-server-process-name)
    ;; TODO: remove the log buffer
-   :buffer (concat "*emdocs-server-log:" (buffer-name buffer) "*")
+   :buffer (emdocs-get-server-process-buffer)
    :family 'ipv4
    :host my-ip
    :service +emdocs-http-port+
-   :sentinel (lambda (sock msg)
-               (emdocs-server-sentinel buffer sock msg))
-   :filter (lambda (sock msg)
-             (emdocs-server-filter buffer sock msg))
+   :sentinel #'emdocs-server-sentinel
+   :filter #'emdocs-server-filter
    :server t
    :noquery t))
 
 (defun emdocs-client-sentinel (buffer sock msg)
-  "docstring")
+  "docstring"
+  (with-current-buffer (emdocs-get-client-process-buffer buffer)
+    (goto-char (point-min))
+    (insert "sentinel:" msg)
+    (newline)))
 
 (defun emdocs-client-filter (buffer sock msg)
-  "docstring")
+  "docstring"
+  (with-current-buffer (emdocs-get-client-process-buffer buffer)
+    (goto-char (point-min))
+    (insert "filter:" msg)
+    (newline))
+  (cond ((string-match "^give your ip and buffer\n$" msg)
+         (process-send-string sock
+          (json-encode `(:buffer ,(buffer-name buffer)
+                         :ip ,(emdocs-get-internal-ip-address)))))))
 
 (defun emdocs-connect-client (buffer ip)
   "docstring"
   (make-network-process
-   :name (concat "*emdocs-client:"
-                 (buffer-name buffer) ":" ip "*")
+   :name (emdocs-get-client-process-name buffer ip)
    ;; TODO: remove the log buffer
-   :buffer (concat "*emdocs-client-log:" (buffer-name buffer) "*")
+   :buffer (emdocs-get-client-process-buffer buffer)
    :family 'ipv4
    :host ip
    :service +emdocs-http-port+

                    (condition-case emdocs-client-list
                        (cons (emdocs-connect-client buffer ip) nil)
                      (file-error 'no-conn))))
            (when (eq emdocs-client-list 'no-conn)
              (message "Client could not connect: exiting.")
              (setq emdocs-mode nil)
              (emdocs-disconnect))))
      (message "Not connected to internet: exiting.")
      (setq emdocs-mode nil)
      (emdocs-disconnect))))

;; -*- lexical-binding: t; -*-

(eval-when-compile
  (require 'cl)
  (require 'json))

;;; globals

(defconst +emdocs-http-port+ 8080
  "docstring")

(defvar *emdocs-server* nil
  "docstring")

;;; functions

;;; utility
(defun emdocs-get-internal-ip-address (&optional device-name)
  "Returns ip address of active interface, ignoring loopback. Returns nil if
none active. Returns an arbitrary interface if more than one is connected."
  (if device-name
      (format-network-address (car (network-interface-info device-name)) t)
    (let ((network-interfaces (network-interface-list)))
