Pārlūkot izejas kodu

Do not use non-blocking sockets in the client (until we have an async API)

Julius Pfrommer 10 gadi atpakaļ
vecāks
revīzija
776266e4e2
3 mainītis faili ar 27 papildinājumiem un 10 dzēšanām
  1. 15 6
      examples/networklayer_tcp.c
  2. 9 1
      include/ua_connection.h
  3. 3 3
      src/client/ua_client.c

+ 15 - 6
examples/networklayer_tcp.c

@@ -47,7 +47,7 @@ static UA_StatusCode socket_write(UA_Connection *connection, const UA_ByteString
         do {
         do {
 #ifdef _WIN32
 #ifdef _WIN32
             n = send((SOCKET)connection->sockfd, (const char*)buf->data, buf->length, 0);
             n = send((SOCKET)connection->sockfd, (const char*)buf->data, buf->length, 0);
-            if(n != 0 &&WSAGetLastError() != WSAEINTR)
+            if(n < 0 && WSAGetLastError() != WSAEINTR)
                 return UA_STATUSCODE_BADCONNECTIONCLOSED;
                 return UA_STATUSCODE_BADCONNECTIONCLOSED;
 #else
 #else
             n = send(connection->sockfd, (const char*)buf->data, buf->length, MSG_NOSIGNAL);
             n = send(connection->sockfd, (const char*)buf->data, buf->length, MSG_NOSIGNAL);
@@ -62,19 +62,28 @@ static UA_StatusCode socket_write(UA_Connection *connection, const UA_ByteString
 
 
 static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout) {
 static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    if(response->data == UA_NULL)
+	if(response->data == UA_NULL)
         retval = connection->getBuffer(connection, response, connection->localConf.recvBufferSize);
         retval = connection->getBuffer(connection, response, connection->localConf.recvBufferSize);
     if(retval != UA_STATUSCODE_GOOD)
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
         return retval;
     struct timeval tmptv = {0, timeout * 1000};
     struct timeval tmptv = {0, timeout * 1000};
     setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmptv, sizeof(struct timeval));
     setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmptv, sizeof(struct timeval));
     int ret = recv(connection->sockfd, (char*)response->data, response->length, 0);
     int ret = recv(connection->sockfd, (char*)response->data, response->length, 0);
-    if(ret <= -1) {
-        if(errno == EAGAIN) {
+	if(ret == 0) {
+		connection->releaseBuffer(connection, response);
+		connection->close(connection);
+		return UA_STATUSCODE_BADCONNECTIONCLOSED;
+	} else if(ret < 0) {
+#ifdef _WIN32
+		if(WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) {
+#else
+		if (errno == EAGAIN) {
+#endif
             return UA_STATUSCODE_BADCOMMUNICATIONERROR;
             return UA_STATUSCODE_BADCOMMUNICATIONERROR;
         }
         }
         connection->releaseBuffer(connection, response);
         connection->releaseBuffer(connection, response);
-        return UA_STATUSCODE_BADINTERNALERROR;
+		connection->close(connection);
+        return UA_STATUSCODE_BADCONNECTIONCLOSED;
     }
     }
     response->length = ret;
     response->length = ret;
     *response = UA_Connection_completeMessages(connection, *response);
     *response = UA_Connection_completeMessages(connection, *response);
@@ -518,7 +527,7 @@ UA_Connection ClientNetworkLayerTCP_connect(char *endpointUrl, UA_Logger *logger
         return connection;
         return connection;
     }
     }
     connection.state = UA_CONNECTION_OPENING;
     connection.state = UA_CONNECTION_OPENING;
-    socket_set_nonblocking(connection.sockfd);
+    //socket_set_nonblocking(connection.sockfd);
     connection.write = socket_write;
     connection.write = socket_write;
     connection.recv = socket_recv;
     connection.recv = socket_recv;
     connection.close = socket_close;
     connection.close = socket_close;

+ 9 - 1
include/ua_connection.h

@@ -67,7 +67,15 @@ struct UA_Connection {
     UA_StatusCode (*getBuffer)(UA_Connection *connection, UA_ByteString *buf, size_t minSize); ///> Attach the data array to the buffer. Fails if minSize is larger than remoteConf allows
     UA_StatusCode (*getBuffer)(UA_Connection *connection, UA_ByteString *buf, size_t minSize); ///> Attach the data array to the buffer. Fails if minSize is larger than remoteConf allows
     void (*releaseBuffer)(UA_Connection *connection, UA_ByteString *buf); ///> Release the buffer
     void (*releaseBuffer)(UA_Connection *connection, UA_ByteString *buf); ///> Release the buffer
     UA_StatusCode (*write)(UA_Connection *connection, const UA_ByteString *buf); ///> The bytestrings cannot be reused after sending!
     UA_StatusCode (*write)(UA_Connection *connection, const UA_ByteString *buf); ///> The bytestrings cannot be reused after sending!
-    UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout); // timeout in milliseconds
+   /**
+     * Receive a message from the remote connection
+	 * @param connection The connection
+	 * @param response The response string. It is allocated by the connection and needs to be freed with connection->releaseBuffer
+     * @param timeout Timeout of the recv operation in milliseconds
+     * @return Returns UA_STATUSCODE_BADCOMMUNICATIONERROR if the recv operation can be repeated, UA_STATUSCODE_GOOD if it succeeded and
+     * UA_STATUSCODE_BADCONNECTIONCLOSED if the connection was closed.
+	 */
+    UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout);
     void (*close)(UA_Connection *connection);
     void (*close)(UA_Connection *connection);
 };
 };
 
 

+ 3 - 3
src/client/ua_client.c

@@ -103,7 +103,7 @@ static UA_StatusCode HelAckHandshake(UA_Client *c) {
     UA_ByteString_init(&reply);
     UA_ByteString_init(&reply);
     do {
     do {
         retval = c->connection.recv(&c->connection, &reply, c->config.timeout);
         retval = c->connection.recv(&c->connection, &reply, c->config.timeout);
-        if(retval == UA_STATUSCODE_BADINTERNALERROR)
+        if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
             return retval;
             return retval;
     } while(retval != UA_STATUSCODE_GOOD);
     } while(retval != UA_STATUSCODE_GOOD);
 
 
@@ -190,7 +190,7 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client) {
     UA_ByteString_init(&reply);
     UA_ByteString_init(&reply);
     do {
     do {
         retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
         retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
-        if(retval == UA_STATUSCODE_BADINTERNALERROR)
+        if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
             return retval;
             return retval;
     } while(retval != UA_STATUSCODE_GOOD);
     } while(retval != UA_STATUSCODE_GOOD);
 
 
@@ -291,7 +291,7 @@ static void sendReceiveRequest(UA_RequestHeader *request, const UA_DataType *req
     UA_ByteString_init(&reply);
     UA_ByteString_init(&reply);
     do {
     do {
         retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
         retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
-        if(retval == UA_STATUSCODE_BADINTERNALERROR) {
+        if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
             respHeader->serviceResult = retval;
             respHeader->serviceResult = retval;
             return;
             return;
         }
         }