CHANGE allow concurrent notifications and RPCs

Fixes cesnet/netopeer2#256
diff --git a/src/session_p.h b/src/session_p.h
index 5a0c899..845fd3f 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -354,11 +354,9 @@
 
     /* Transport implementation */
     NC_TRANSPORT_IMPL ti_type;   /**< transport implementation type to select items from ti union */
-    pthread_mutex_t *ti_lock;    /**< lock to access ti. Note that in case of libssh TI, it can be shared with other
-                                      NETCONF sessions on the same SSH session (but different SSH channel) */
-    pthread_cond_t *ti_cond;     /**< ti_inuse condition */
-    volatile int *ti_inuse;      /**< variable indicating whether TI is being communicated on or not, protected by
-                                      ti_cond and ti_lock */
+    pthread_mutex_t *io_lock;    /**< input/output lock, note that in case of libssh TI, it will be shared
+                                      with other NETCONF sessions on the same SSH session (but different SSH channel) */
+
     union {
         struct {
             int in;              /**< input file descriptor */
@@ -406,6 +404,12 @@
             time_t session_start;          /**< real time the session was created */
             time_t last_rpc;               /**< monotonic time (seconds) the last RPC was received on this session */
             int ntf_status;                /**< flag whether the session is subscribed to any stream */
+
+            pthread_mutex_t *rpc_lock;   /**< lock indicating RPC processing, this lock is always locked before io_lock!! */
+            pthread_cond_t *rpc_cond;    /**< RPC condition (tied with rpc_lock and rpc_inuse) */
+            volatile int *rpc_inuse;     /**< variable indicating whether there is RPC being processed or not (tied with
+                                              rpc_cond and rpc_lock) */
+
             pthread_mutex_t *ch_lock;      /**< Call Home thread lock */
             pthread_cond_t *ch_cond;       /**< Call Home thread condition */
 
@@ -460,7 +464,7 @@
 
 void *nc_realloc(void *ptr, size_t size);
 
-NC_MSG_TYPE nc_send_msg(struct nc_session *session, struct lyd_node *op);
+NC_MSG_TYPE nc_send_msg_io(struct nc_session *session, int io_timeout, struct lyd_node *op);
 
 #ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
 int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime);
@@ -474,11 +478,15 @@
 
 void nc_addtimespec(struct timespec *ts, uint32_t msec);
 
-struct nc_session *nc_new_session(int not_allocate_ti);
+struct nc_session *nc_new_session(NC_SIDE side, int shared_ti);
 
-int nc_session_lock(struct nc_session *session, int timeout, const char *func);
+int nc_session_rpc_lock(struct nc_session *session, int timeout, const char *func);
 
-int nc_session_unlock(struct nc_session *session, int timeout, const char *func);
+int nc_session_rpc_unlock(struct nc_session *session, int timeout, const char *func);
+
+int nc_session_io_lock(struct nc_session *session, int timeout, const char *func);
+
+int nc_session_io_unlock(struct nc_session *session, const char *func);
 
 int nc_ps_lock(struct nc_pollsession *ps, uint8_t *id, const char *func);
 
@@ -501,7 +509,7 @@
  * @return NC_MSG_HELLO on success, NC_MSG_BAD_HELLO on client \<hello\> message parsing fail
  * (server-side only), NC_MSG_WOULDBLOCK on timeout, NC_MSG_ERROR on other error.
  */
-NC_MSG_TYPE nc_handshake(struct nc_session *session);
+NC_MSG_TYPE nc_handshake_io(struct nc_session *session);
 
 /**
  * @brief Create a socket connection.
@@ -680,14 +688,14 @@
  * libyang XML tree and the message type is detected from the top level element.
  *
  * @param[in] session NETCONF session from which the message is being read.
- * @param[in] timeout Timeout in milliseconds. Negative value means infinite timeout,
+ * @param[in] io_timeout Timeout in milliseconds. Negative value means infinite timeout,
  *            zero value causes to return immediately.
  * @param[out] data XML tree built from the read data.
  * @return Type of the read message. #NC_MSG_WOULDBLOCK is returned if timeout is positive
  * (or zero) value and it passed out without any data on the wire. #NC_MSG_ERROR is
  * returned on error and #NC_MSG_NONE is never returned by this function.
  */
-NC_MSG_TYPE nc_read_msg_poll(struct nc_session* session, int timeout, struct lyxml_elem **data);
+NC_MSG_TYPE nc_read_msg_poll_io(struct nc_session* session, int io_timeout, struct lyxml_elem **data);
 
 /**
  * @brief Read message from the wire.
@@ -696,17 +704,23 @@
  * libyang XML tree and the message type is detected from the top level element.
  *
  * @param[in] session NETCONF session from which the message is being read.
+ * @param[in] io_timeout Timeout in milliseconds. Negative value means infinite timeout,
+ *            zero value causes to return immediately.
  * @param[out] data XML tree built from the read data.
+ * @param[in] passing_io_lock True if \p session IO lock is already held. This function always unlocks
+ *            it before returning!
  * @return Type of the read message. #NC_MSG_WOULDBLOCK is returned if timeout is positive
  * (or zero) value and it passed out without any data on the wire. #NC_MSG_ERROR is
  * returned on error and #NC_MSG_NONE is never returned by this function.
  */
-NC_MSG_TYPE nc_read_msg(struct nc_session* session, struct lyxml_elem **data);
+NC_MSG_TYPE nc_read_msg_io(struct nc_session* session, int io_timeout, struct lyxml_elem **data, int passing_io_lock);
 
 /**
  * @brief Write message into wire.
  *
  * @param[in] session NETCONF session to which the message will be written.
+ * @param[in] io_timeout Timeout in milliseconds. Negative value means infinite timeout,
+ *            zero value causes to return immediately.
  * @param[in] type The type of the message to write, specified as #NC_MSG_TYPE value. According to the type, the
  * specific additional parameters are required or accepted:
  * - #NC_MSG_RPC
@@ -719,10 +733,16 @@
  *   - `struct lyxml_node *rpc_elem;` - root of the RPC object to reply to. Required parameter.
  *   - `struct nc_server_reply *reply;` - RPC reply. Required parameter.
  * - #NC_MSG_NOTIF
- *   - TODO: content
- * @return 0 on success
+ *   - `struct nc_server_notif *notif;` - notification object. Required parameter.
+ * - #NC_MSG_HELLO
+ *   - `const char **capabs;` - capabilities array ended with NULL. Required parameter.
+ *   - `uint32_t *sid;` - session ID to be included in the hello message. Optional parameter.
+ *
+ * @return Type of the written message. #NC_MSG_WOULDBLOCK is returned if timeout is positive
+ * (or zero) value and IO lock could not be acquired in that time. #NC_MSG_ERROR is
+ * returned on error and #NC_MSG_NONE is never returned by this function.
  */
-int nc_write_msg(struct nc_session *session, int type, ...);
+NC_MSG_TYPE nc_write_msg_io(struct nc_session *session, int io_timeout, int type, ...);
 
 /**
  * @brief Check whether a session is still connected (on transport layer).