summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xPICA_client.c253
-rw-r--r--PICA_common.h4
2 files changed, 211 insertions, 46 deletions
diff --git a/PICA_client.c b/PICA_client.c
index 141d35c..29b6955 100755
--- a/PICA_client.c
+++ b/PICA_client.c
@@ -390,11 +390,8 @@ BIO_free(mem);
chnl->state=PICA_C2C_STATE_ACTIVE;
-{
-unsigned long arg = 1;
+IOCTLSETNONBLOCKINGSOCKET(chnl->sck_data, 1);
-IOCTLSETNONBLOCKINGSOCKET(chnl->sck_data, &arg);
-}
return PICA_OK;
@@ -1223,6 +1220,74 @@ free(a);
return ret_err;
}
+static int c2n_stage2_sendreq(struct PICA_c2n *c2n)
+{
+struct PICA_proto_msg *mp;
+
+puts("c2n_stage2_sendreq");//debug
+
+mp = c2n_writebuf_push(c2n, PICA_PROTO_INITREQ, PICA_PROTO_INITREQ_SIZE);
+
+if (mp)
+ {
+ mp->tail[0] = PICA_PROTO_VER_HIGH;
+ mp->tail[1] = PICA_PROTO_VER_LOW;
+ }
+else
+ return PICA_ERRNOMEM;
+
+c2n->state = PICA_C2N_STATE_WAITINGREP;
+
+return PICA_OK;
+}
+
+static int c2n_stage3_starttls(struct PICA_c2n *c2n)
+{
+int ret;
+
+ret = SSL_set_fd(c2n->ssl_comm, c2n->sck_comm);
+
+if (ret != 1)
+ return PICA_ERRSSL;
+
+ret = SSL_accept(c2n->ssl_comm);
+
+if (ret == 0)
+ return PICA_ERRSSL;
+
+if (ret < 0)
+ {
+ ret = SSL_get_error(c2n->ssl_comm, ret);
+
+ if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
+ return PICA_ERRSSL;
+ }
+
+c2n->state = PICA_C2N_STATE_WAITINGTLS;
+
+return PICA_OK;
+}
+
+static int c2n_stage4_nodelistrequest(struct PICA_c2n *c2n)
+{
+struct PICA_proto_msg *mp;
+
+mp = c2n_writebuf_push(c2n, PICA_PROTO_CLNODELISTREQ, PICA_PROTO_CLNODELISTREQ_SIZE);
+
+if (mp)
+ {
+ RAND_bytes(mp->tail, 2);
+ }
+else
+ return PICA_ERRNOMEM;
+
+c2n->state = PICA_C2N_STATE_CONNECTED;
+
+callbacks.c2n_established_cb(c2n);
+
+return PICA_OK;
+}
+
/*адрес сервера, сертификат клиента и закрытый ключ*/
//Осуществляет подключение к серверу по указанному адресу.
@@ -1315,37 +1380,33 @@ if (cid->sck_comm==SOCKET_ERROR)
goto error_ret_3;
}
+IOCTLSETNONBLOCKINGSOCKET(cid->sck_comm, 1);
+
cid->state = PICA_C2N_STATE_CONNECTING;
-ret=connect(cid->sck_comm,(struct sockaddr*)&a,sizeof(struct sockaddr_in));
+ret=connect(cid->sck_comm,(struct sockaddr*)&cid->srv_addr,sizeof(cid->srv_addr));
/////////////////state_
+if (ret == 0)
+ return c2n_stage2_sendreq(cid);
+
if (ret==SOCKET_ERROR)
{
+#ifndef WIN32
+ if (errno == EINPROGRESS || errno == EINTR)
+ return PICA_OK;
+#else
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ return PICA_OK;
+#endif
+
ret_err=PICA_ERRSOCK;
goto error_ret_4;
}
-{
-struct PICA_proto_msg *mp;
-
-mp = c2n_writebuf_push( cid, PICA_PROTO_INITREQ, PICA_PROTO_INITREQ_SIZE);
-
-if (mp)
- {
- mp->tail[0] = PICA_PROTO_VER_HIGH;
- mp->tail[1] = PICA_PROTO_VER_LOW;
- }
-else
- {
- ret_err = PICA_ERRNOMEM;
- goto error_ret_4;
- }
-}
-
-//cid->state = PICA_C2N_STATE_WAITINGREP;
+/*
do
{
ret = PICA_write_c2n(cid);
@@ -1378,7 +1439,7 @@ if (cid->init_resp_ok != 1)
}
//printf("6\n");//debug
-
+*/ /*
ret=SSL_set_fd(cid->ssl_comm,cid->sck_comm);
//printf("SSL_set_fd=%i\n",ret);
@@ -1392,7 +1453,7 @@ if (ret!=1)
//ERR_CHECK
ret_err=PICA_ERRSSL;
goto error_ret_4;
- }
+ }*/ /*
cid->state = PICA_C2N_STATE_CONNECTED;//<<<!!!
{
@@ -1405,12 +1466,7 @@ if (mp)
RAND_bytes(mp->tail, 2);
}
}
-
-{
-unsigned long arg = 1;
-
-IOCTLSETNONBLOCKINGSOCKET(cid->sck_comm, &arg);
-}
+*/
return PICA_OK;
@@ -1464,12 +1520,107 @@ return PICA_OK;
static int process_c2n(struct PICA_c2n *c2n, fd_set *rfds, fd_set *wfds)
{
-//switch(c2n->state)
-// {
-// case PICA_C2N_STATE_CONNECTED:
-// }
+int ret = PICA_OK;
-return PICA_OK;
+//puts("process_c2n()");//debug
+
+switch(c2n->state)
+ {
+ case PICA_C2N_STATE_NEW:
+ break;
+
+ case PICA_C2N_STATE_CONNECTING:
+
+ if (FD_ISSET(c2n->sck_comm, wfds))
+ {
+ ret = PICA_ERRSOCK;
+
+ //check if connect() finished successfully
+#ifndef WIN32
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ if (0 == getsockopt(c2n->sck_comm, SOL_SOCKET, SO_ERROR, &optval, &optlen))
+ {
+ if (optval == 0)
+ {
+ ret = c2n_stage2_sendreq(c2n);
+ }
+ }
+#else
+ if (SOCKET_ERROR == connect(c2n->ssl_comm, (struct sockaddr*)&c2n->srv_addr, sizeof(c2n->srv_addr)) &&
+ WSAEISCONN == WSAGetLastError())
+ {
+ ret = c2n_stage2_sendreq(c2n);
+ }
+#endif
+ }
+
+ break;
+
+ case PICA_C2N_STATE_WAITINGREP:
+
+ if (FD_ISSET(c2n->sck_comm, wfds))
+ {
+ ret = PICA_write_c2n(c2n);
+ }
+
+ if (FD_ISSET(c2n->sck_comm, rfds))
+ {
+ ret = PICA_read_c2n(c2n);
+ }
+
+ if (ret == PICA_OK && c2n->init_resp_ok != 0)
+ {
+ if (c2n->init_resp_ok == 1)
+ ret = c2n_stage3_starttls(c2n);
+ else
+ {
+ if (c2n->node_ver_major > PICA_PROTO_VER_HIGH ||
+ (c2n->node_ver_major == PICA_PROTO_VER_HIGH && c2n->node_ver_minor > PICA_PROTO_VER_LOW))
+ ret = PICA_ERRPROTONEW;
+ else
+ ret = PICA_ERRPROTOOLD;
+ }
+ }
+
+ break;
+
+ case PICA_C2N_STATE_WAITINGTLS:
+
+ if (FD_ISSET(c2n->sck_comm, wfds) || FD_ISSET(c2n->sck_comm, rfds))
+ {
+ int sslret;
+
+ sslret = SSL_accept(c2n->ssl_comm);
+
+ if (sslret == 1)
+ ret = c2n_stage4_nodelistrequest(c2n);
+ else if (sslret == 0)
+ ret = PICA_ERRSSL;
+ else if (sslret < 0)
+ {
+ sslret = SSL_get_error(c2n->ssl_comm, sslret);
+
+ if (sslret != SSL_ERROR_WANT_READ && sslret != SSL_ERROR_WANT_WRITE)
+ ret = PICA_ERRSSL;
+ }
+ }
+
+ break;
+
+ case PICA_C2N_STATE_CONNECTED:
+
+ if (FD_ISSET(c2n->sck_comm, wfds))
+ ret = PICA_write_c2n(c2n);
+
+ if (FD_ISSET(c2n->sck_comm, rfds))
+ ret = PICA_read_c2n(c2n);
+
+ break;
+ }
+
+return ret;
}
static int process_c2c(struct PICA_c2c *c2c, fd_set *rfds, fd_set *wfds)
@@ -1502,6 +1653,8 @@ int ret, nfds = 0;
struct PICA_c2n **ic2n;
struct PICA_listener **ilst;
+//puts("PICA_event_loop");//debug
+
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
@@ -1522,9 +1675,12 @@ while(ic2n && *ic2n)
{
struct PICA_c2c *ic2c;
+ //printf("event_loop: adding c2n %p\n", *ic2n);//debug
+
fdset_add(&rfds, (*ic2n)->sck_comm, &nfds);
- if ((*ic2n)->write_pos)
+ if ((*ic2n)->write_pos || (*ic2n)->state == PICA_C2N_STATE_CONNECTING
+ || (*ic2n)->state == PICA_C2N_STATE_WAITINGTLS)
fdset_add(&wfds, (*ic2n)->sck_comm, &nfds);
ic2c = (*ic2n)->chan_list_head;
@@ -1535,7 +1691,7 @@ while(ic2n && *ic2n)
{
fdset_add(&rfds, ic2c->sck_data, &nfds);
- if (ic2c->write_pos)
+ if (ic2c->write_pos || ic2c->sendfilestate == PICA_CHANSENDFILESTATE_SENDING)
fdset_add(&wfds, ic2c->sck_data, &nfds);
}
@@ -1548,9 +1704,6 @@ while(ic2n && *ic2n)
ret = select(nfds + 1, &rfds, &wfds, NULL, &tv);
-if (ret == 0)
- return PICA_OK;
-
if (ret == -1)
{
#ifndef WIN32
@@ -1563,6 +1716,8 @@ if (ret == -1)
#endif
}
+//printf("select() returned %i\n", ret);//debug
+
//processing listeners, c2n and c2c connections
ilst = listeners;
@@ -1572,11 +1727,16 @@ while(ilst && *ilst)
ret = process_listener(*ilst, &rfds);
if (ret != PICA_OK)
+ {
callbacks.listener_error(*ilst, ret);
+ PICA_close_listener(*ilst);
+ }
ilst++;
}
+ic2n = connections;
+
while(ic2n && *ic2n)
{
struct PICA_c2c *ic2c;
@@ -1587,6 +1747,11 @@ while(ic2n && *ic2n)
if (ret != PICA_OK)
{
+ if ((*ic2n)->state == PICA_C2N_STATE_CONNECTED)
+ callbacks.c2n_closed_cb(*ic2n);
+ else
+ callbacks.c2n_failed_cb(*ic2n);
+
PICA_close_c2n(*ic2n);
}
else
@@ -1822,7 +1987,7 @@ int PICA_write_c2n(struct PICA_c2n *ci)
{
int ret = PICA_ERRINVARG;
-if (PICA_C2N_STATE_CONNECTING == ci->state)
+if (PICA_C2N_STATE_WAITINGREP == ci->state)
ret = PICA_write_socket( ci->sck_comm, ci->write_buf, &ci->write_pos);
else if (PICA_C2N_STATE_CONNECTED == ci->state)
ret = PICA_write_ssl( ci->ssl_comm, ci->write_buf, &ci->write_pos, &ci->write_sslbytestowrite);
@@ -1940,7 +2105,7 @@ int ret;
//ret=SSL_read(ci->ssl_comm, ci->read_buf + ci->read_pos, PICA_CONNREADBUFSIZE - ci->read_pos);
-if (PICA_C2N_STATE_CONNECTING == ci->state)
+if (PICA_C2N_STATE_WAITINGREP == ci->state)
ret = PICA_read_socket(ci->sck_comm, ci->read_buf, &ci->read_pos, PICA_CONNREADBUFSIZE);
else if (PICA_C2N_STATE_CONNECTED == ci->state)
ret = PICA_read_ssl(ci->ssl_comm, ci->read_buf, &ci->read_pos, PICA_CONNREADBUFSIZE);
@@ -1949,7 +2114,7 @@ else if (PICA_C2N_STATE_CONNECTED == ci->state)
if (ret == PICA_OK)
{
- if (PICA_C2N_STATE_CONNECTING == ci->state)
+ if (PICA_C2N_STATE_WAITINGREP == ci->state)
if(!PICA_processdatastream( ci->read_buf, &(ci->read_pos), ci, c2n_init_messages, MSGINFO_MSGSNUM(c2n_init_messages)))
return PICA_ERRSERV;
diff --git a/PICA_common.h b/PICA_common.h
index dd92b32..db14f99 100644
--- a/PICA_common.h
+++ b/PICA_common.h
@@ -4,11 +4,11 @@
#ifdef WIN32
#define CLOSE closesocket
#define SHUTDOWN(s) shutdown(s,SD_BOTH)
-#define IOCTLSETNONBLOCKINGSOCKET(s, arg) ioctlsocket(s, FIONBIO, (unsigned long*)(arg))
+#define IOCTLSETNONBLOCKINGSOCKET(s, a) {unsigned long arg = (a); ioctlsocket(s, FIONBIO, (unsigned long*)&arg); }
#else
#define CLOSE close
#define SHUTDOWN(s) shutdown(s,SHUT_RDWR)
-#define IOCTLSETNONBLOCKINGSOCKET(s, arg) ioctl(s, FIONBIO, (int*)(arg))
+#define IOCTLSETNONBLOCKINGSOCKET(s, a) {int arg = (a); ioctl(s, FIONBIO, (int*)&arg); }
#endif
#ifdef WIN32