- if (event & YAZ_SOCKET_OBSERVE_READ)
- {
- int res;
- COMSTACK new_line;
-
- if ((res = cs_listen(m_cs, 0, 0)) == 1)
- return;
- if (res < 0)
- {
- logf(LOG_FATAL, "cs_listen failed");
- return;
- }
- if (!(new_line = cs_accept(m_cs)))
- return;
-
- Yaz_PDU_Assoc *assoc = new Yaz_PDU_Assoc (m_socketObservable,
- new_line);
- assoc->m_parent = this;
- assoc->m_next = m_children;
- m_children = assoc;
-
- assoc->m_PDU_Observer = m_PDU_Observer->clone(assoc);
- assoc->m_state = Ready;
- assoc->m_socketObservable->addObserver(cs_fileno(new_line), assoc);
- assoc->m_socketObservable->maskObserver(assoc,
- YAZ_SOCKET_OBSERVE_READ|
- YAZ_SOCKET_OBSERVE_EXCEPT);
- }
+ case PDU_Assoc_priv::Accepting:
+ if (!cs_accept(m_p->cs))
+ {
+ yaz_log(m_p->log, "PDU_Assoc::cs_accept failed");
+ m_p->cs = 0;
+ shutdown();
+ m_PDU_Observer->failNotify();
+ }
+ else
+ {
+ unsigned mask = 0;
+ if (m_p->cs->io_pending & CS_WANT_WRITE)
+ mask |= SOCKET_OBSERVE_WRITE;
+ if (m_p->cs->io_pending & CS_WANT_READ)
+ mask |= SOCKET_OBSERVE_READ;
+ if (!mask)
+ { // accept is complete. turn to ready state and write if needed
+ m_p->state = PDU_Assoc_priv::Ready;
+ flush_PDU();
+ }
+ else
+ { // accept still incomplete.
+ yaz_log(m_p->log, "maskObserver 2");
+ m_p->m_socketObservable->maskObserver(this,
+ mask|SOCKET_OBSERVE_EXCEPT);
+ }
+ }
+ break;
+ case PDU_Assoc_priv::Connecting:
+ if (event & SOCKET_OBSERVE_READ &&
+ event & SOCKET_OBSERVE_WRITE)
+ {
+ // For Unix: if both read and write is set, then connect failed.
+ shutdown();
+ m_PDU_Observer->failNotify();
+ }
+ else
+ {
+ yaz_log(m_p->log, "cs_rcvconnect");
+ int res = cs_rcvconnect(m_p->cs);
+ if (res == 1)
+ {
+ unsigned mask = SOCKET_OBSERVE_EXCEPT;
+ if (m_p->cs->io_pending & CS_WANT_WRITE)
+ mask |= SOCKET_OBSERVE_WRITE;
+ if (m_p->cs->io_pending & CS_WANT_READ)
+ mask |= SOCKET_OBSERVE_READ;
+ yaz_log(m_p->log, "maskObserver 3");
+ m_p->m_socketObservable->maskObserver(this, mask);
+ }
+ else
+ {
+ m_p->state = PDU_Assoc_priv::Ready;
+ if (m_PDU_Observer)
+ m_PDU_Observer->connectNotify();
+ flush_PDU();
+ }
+ }
+ break;
+ case PDU_Assoc_priv::Listen:
+ if (event & SOCKET_OBSERVE_READ)
+ {
+ int res;
+ COMSTACK new_line;
+
+ if ((res = cs_listen(m_p->cs, 0, 0)) == 1)
+ return;
+ if (res < 0)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "cs_listen failed");
+ return;
+ }
+ if (!(new_line = cs_accept(m_p->cs)))
+ return;
+ /* 1. create socket-manager
+ 2. create pdu-assoc
+ 3. create top-level object
+ setup observer for child fileid in pdu-assoc
+ 4. start thread
+ */
+ yaz_log(m_p->log, "new session: parent fd=%d child fd=%d",
+ cs_fileno(m_p->cs), cs_fileno(new_line));
+ childNotify(new_line);
+ }
+ break;
+ case PDU_Assoc_priv::Writing:
+ if (event & (SOCKET_OBSERVE_READ|SOCKET_OBSERVE_WRITE))
+ flush_PDU();
+ break;
+ case PDU_Assoc_priv::Ready:
+ if (event & (SOCKET_OBSERVE_READ|SOCKET_OBSERVE_WRITE))
+ {
+ do
+ {
+ int res = cs_get(m_p->cs, &m_p->input_buf, &m_p->input_len);
+ if (res == 1)
+ {
+ unsigned mask = SOCKET_OBSERVE_EXCEPT;
+ if (m_p->cs->io_pending & CS_WANT_WRITE)
+ mask |= SOCKET_OBSERVE_WRITE;
+ if (m_p->cs->io_pending & CS_WANT_READ)
+ mask |= SOCKET_OBSERVE_READ;
+ yaz_log(m_p->log, "maskObserver 4");
+ m_p->m_socketObservable->maskObserver(this, mask);
+ return;
+ }
+ else if (res <= 0)
+ {
+ yaz_log(m_p->log, "PDU_Assoc::Connection closed by peer");
+ shutdown();
+ if (m_PDU_Observer)
+ m_PDU_Observer->failNotify(); // problem here..
+ return;
+ }
+ // lock it, so we know if recv_PDU deletes it.
+ int destroyed = 0;
+ m_p->destroyed = &destroyed;
+
+ if (!m_PDU_Observer)
+ return;
+#if 0
+ PDU_Assoc_priv::PDU_Queue **pq = &m_p->m_queue_in;
+ while (*pq)
+ pq = &(*pq)->m_next;
+
+ *pq = new PDU_Assoc_priv::PDU_Queue(m_p->m_input_buf, res);
+#else
+ m_PDU_Observer->recv_PDU(m_p->input_buf, res);
+#endif
+ if (destroyed) // it really was destroyed, return now.
+ return;
+ m_p->destroyed = 0;
+ } while (m_p->cs && cs_more(m_p->cs));
+ if (m_p->cs && m_p->state == PDU_Assoc_priv::Ready)
+ {
+ yaz_log(m_p->log, "maskObserver 5");
+ m_p->m_socketObservable->maskObserver(this,
+ SOCKET_OBSERVE_EXCEPT|
+ SOCKET_OBSERVE_READ);
+ }
+ }
+ break;
+ case PDU_Assoc_priv::Closed:
+ yaz_log(m_p->log, "CLOSING state=%d event was %d", m_p->state,
+ event);
+ shutdown();
+ m_PDU_Observer->failNotify();
+ break;
+ default:
+ yaz_log(m_p->log, "Unknown state=%d event was %d", m_p->state, event);
+ shutdown();
+ m_PDU_Observer->failNotify();