ua_network_tcp.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  2. * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  3. *
  4. * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  5. * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
  6. * Copyright 2017 (c) frax2222
  7. * Copyright 2017 (c) Jose Cabral
  8. * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
  9. */
  10. #include "ua_network_tcp.h"
  11. #include "ua_log_stdout.h"
  12. #include "../deps/queue.h"
  13. #include "ua_util.h"
  14. #include <string.h> // memset
  15. #ifndef MSG_NOSIGNAL
  16. #define MSG_NOSIGNAL 0
  17. #endif
  18. /****************************/
  19. /* Generic Socket Functions */
  20. /****************************/
  21. static UA_StatusCode
  22. connection_getsendbuffer(UA_Connection *connection,
  23. size_t length, UA_ByteString *buf) {
  24. if(length > connection->config.sendBufferSize)
  25. return UA_STATUSCODE_BADCOMMUNICATIONERROR;
  26. return UA_ByteString_allocBuffer(buf, length);
  27. }
  28. static void
  29. connection_releasesendbuffer(UA_Connection *connection,
  30. UA_ByteString *buf) {
  31. UA_ByteString_deleteMembers(buf);
  32. }
  33. static void
  34. connection_releaserecvbuffer(UA_Connection *connection,
  35. UA_ByteString *buf) {
  36. UA_ByteString_deleteMembers(buf);
  37. }
  38. static UA_StatusCode
  39. connection_write(UA_Connection *connection, UA_ByteString *buf) {
  40. if(connection->state == UA_CONNECTION_CLOSED) {
  41. UA_ByteString_deleteMembers(buf);
  42. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  43. }
  44. /* Prevent OS signals when sending to a closed socket */
  45. int flags = 0;
  46. flags |= MSG_NOSIGNAL;
  47. /* Send the full buffer. This may require several calls to send */
  48. size_t nWritten = 0;
  49. do {
  50. ssize_t n = 0;
  51. do {
  52. size_t bytes_to_send = buf->length - nWritten;
  53. n = UA_send(connection->sockfd,
  54. (const char*)buf->data + nWritten,
  55. bytes_to_send, flags);
  56. if(n < 0 && UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_AGAIN) {
  57. connection->close(connection);
  58. UA_ByteString_deleteMembers(buf);
  59. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  60. }
  61. } while(n < 0);
  62. nWritten += (size_t)n;
  63. } while(nWritten < buf->length);
  64. /* Free the buffer */
  65. UA_ByteString_deleteMembers(buf);
  66. return UA_STATUSCODE_GOOD;
  67. }
  68. static UA_StatusCode
  69. connection_recv(UA_Connection *connection, UA_ByteString *response,
  70. UA_UInt32 timeout) {
  71. if(connection->state == UA_CONNECTION_CLOSED)
  72. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  73. /* Listen on the socket for the given timeout until a message arrives */
  74. if(timeout > 0) {
  75. fd_set fdset;
  76. FD_ZERO(&fdset);
  77. UA_fd_set(connection->sockfd, &fdset);
  78. UA_UInt32 timeout_usec = timeout * 1000;
  79. struct timeval tmptv = {(long int)(timeout_usec / 1000000),
  80. (long int)(timeout_usec % 1000000)};
  81. int resultsize = UA_select(connection->sockfd+1, &fdset, NULL,
  82. NULL, &tmptv);
  83. /* No result */
  84. if(resultsize == 0)
  85. return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
  86. if(resultsize == -1) {
  87. /* The call to select was interrupted manually. Act as if it timed
  88. * out */
  89. if(errno == EINTR)
  90. return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
  91. /* The error cannot be recovered. Close the connection. */
  92. connection->close(connection);
  93. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  94. }
  95. }
  96. response->data = (UA_Byte*)
  97. UA_malloc(connection->config.recvBufferSize);
  98. if(!response->data) {
  99. response->length = 0;
  100. return UA_STATUSCODE_BADOUTOFMEMORY; /* not enough memory retry */
  101. }
  102. /* Get the received packet(s) */
  103. ssize_t ret = UA_recv(connection->sockfd, (char*)response->data,
  104. connection->config.recvBufferSize, 0);
  105. /* The remote side closed the connection */
  106. if(ret == 0) {
  107. UA_ByteString_deleteMembers(response);
  108. connection->close(connection);
  109. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  110. }
  111. /* Error case */
  112. if(ret < 0) {
  113. UA_ByteString_deleteMembers(response);
  114. if(UA_ERRNO == UA_INTERRUPTED || (timeout > 0) ?
  115. false : (UA_ERRNO == UA_EAGAIN || UA_ERRNO == UA_WOULDBLOCK))
  116. return UA_STATUSCODE_GOOD; /* statuscode_good but no data -> retry */
  117. connection->close(connection);
  118. return UA_STATUSCODE_BADCONNECTIONCLOSED;
  119. }
  120. /* Set the length of the received buffer */
  121. response->length = (size_t)ret;
  122. return UA_STATUSCODE_GOOD;
  123. }
  124. /***************************/
  125. /* Server NetworkLayer TCP */
  126. /***************************/
  127. #define MAXBACKLOG 100
  128. #define NOHELLOTIMEOUT 120000 /* timeout in ms before close the connection
  129. * if server does not receive Hello Message */
  130. typedef struct ConnectionEntry {
  131. UA_Connection connection;
  132. LIST_ENTRY(ConnectionEntry) pointers;
  133. } ConnectionEntry;
  134. typedef struct {
  135. UA_Logger logger;
  136. UA_UInt16 port;
  137. UA_SOCKET serverSockets[FD_SETSIZE];
  138. UA_UInt16 serverSocketsSize;
  139. LIST_HEAD(, ConnectionEntry) connections;
  140. } ServerNetworkLayerTCP;
  141. static void
  142. ServerNetworkLayerTCP_freeConnection(UA_Connection *connection) {
  143. UA_Connection_deleteMembers(connection);
  144. UA_free(connection);
  145. }
  146. /* This performs only 'shutdown'. 'close' is called when the shutdown
  147. * socket is returned from select. */
  148. static void
  149. ServerNetworkLayerTCP_close(UA_Connection *connection) {
  150. if (connection->state == UA_CONNECTION_CLOSED)
  151. return;
  152. UA_shutdown((UA_SOCKET)connection->sockfd, 2);
  153. connection->state = UA_CONNECTION_CLOSED;
  154. }
  155. static UA_StatusCode
  156. ServerNetworkLayerTCP_add(UA_ServerNetworkLayer *nl, ServerNetworkLayerTCP *layer,
  157. UA_Int32 newsockfd, struct sockaddr_storage *remote) {
  158. /* Set nonblocking */
  159. UA_socket_set_nonblocking(newsockfd);//TODO: check return value
  160. /* Do not merge packets on the socket (disable Nagle's algorithm) */
  161. int dummy = 1;
  162. if(UA_setsockopt(newsockfd, IPPROTO_TCP, TCP_NODELAY,
  163. (const char *)&dummy, sizeof(dummy)) < 0) {
  164. UA_LOG_SOCKET_ERRNO_WRAP(
  165. UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK,
  166. "Cannot set socket option TCP_NODELAY. Error: %s",
  167. errno_str));
  168. return UA_STATUSCODE_BADUNEXPECTEDERROR;
  169. }
  170. #if defined(UA_getnameinfo)
  171. /* Get the peer name for logging */
  172. char remote_name[100];
  173. int res = UA_getnameinfo((struct sockaddr*)remote,
  174. sizeof(struct sockaddr_storage),
  175. remote_name, sizeof(remote_name),
  176. NULL, 0, NI_NUMERICHOST);
  177. if(res == 0) {
  178. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  179. "Connection %i | New connection over TCP from %s",
  180. (int)newsockfd, remote_name);
  181. } else {
  182. UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  183. "Connection %i | New connection over TCP, "
  184. "getnameinfo failed with error: %s",
  185. (int)newsockfd, errno_str));
  186. }
  187. #else
  188. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  189. "Connection %i | New connection over TCP",
  190. (int)newsockfd);
  191. #endif
  192. /* Allocate and initialize the connection */
  193. ConnectionEntry *e = (ConnectionEntry*)UA_malloc(sizeof(ConnectionEntry));
  194. if(!e){
  195. UA_close(newsockfd);
  196. return UA_STATUSCODE_BADOUTOFMEMORY;
  197. }
  198. UA_Connection *c = &e->connection;
  199. memset(c, 0, sizeof(UA_Connection));
  200. c->sockfd = newsockfd;
  201. c->handle = layer;
  202. c->config = nl->localConnectionConfig;
  203. c->send = connection_write;
  204. c->close = ServerNetworkLayerTCP_close;
  205. c->free = ServerNetworkLayerTCP_freeConnection;
  206. c->getSendBuffer = connection_getsendbuffer;
  207. c->releaseSendBuffer = connection_releasesendbuffer;
  208. c->releaseRecvBuffer = connection_releaserecvbuffer;
  209. c->state = UA_CONNECTION_OPENING;
  210. c->openingDate = UA_DateTime_nowMonotonic();
  211. /* Add to the linked list */
  212. LIST_INSERT_HEAD(&layer->connections, e, pointers);
  213. return UA_STATUSCODE_GOOD;
  214. }
  215. static void
  216. addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
  217. /* Create the server socket */
  218. UA_SOCKET newsock = UA_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  219. if(newsock == UA_INVALID_SOCKET)
  220. {
  221. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  222. "Error opening the server socket");
  223. return;
  224. }
  225. /* Some Linux distributions have net.ipv6.bindv6only not activated. So
  226. * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use
  227. * AF_INET6 sockets only for IPv6. */
  228. int optval = 1;
  229. #if UA_IPV6
  230. if(ai->ai_family == AF_INET6 &&
  231. UA_setsockopt(newsock, IPPROTO_IPV6, IPV6_V6ONLY,
  232. (const char*)&optval, sizeof(optval)) == -1) {
  233. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  234. "Could not set an IPv6 socket to IPv6 only");
  235. UA_close(newsock);
  236. return;
  237. }
  238. #endif
  239. if(UA_setsockopt(newsock, SOL_SOCKET, SO_REUSEADDR,
  240. (const char *)&optval, sizeof(optval)) == -1) {
  241. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  242. "Could not make the socket reusable");
  243. UA_close(newsock);
  244. return;
  245. }
  246. if(UA_socket_set_nonblocking(newsock) != UA_STATUSCODE_GOOD) {
  247. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  248. "Could not set the server socket to nonblocking");
  249. UA_close(newsock);
  250. return;
  251. }
  252. /* Bind socket to address */
  253. if(UA_bind(newsock, ai->ai_addr, (socklen_t)ai->ai_addrlen) < 0) {
  254. UA_LOG_SOCKET_ERRNO_WRAP(
  255. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  256. "Error binding a server socket: %s", errno_str));
  257. UA_close(newsock);
  258. return;
  259. }
  260. /* Start listening */
  261. if(UA_listen(newsock, MAXBACKLOG) < 0) {
  262. UA_LOG_SOCKET_ERRNO_WRAP(
  263. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  264. "Error listening on server socket: %s", errno_str));
  265. UA_close(newsock);
  266. return;
  267. }
  268. layer->serverSockets[layer->serverSocketsSize] = newsock;
  269. layer->serverSocketsSize++;
  270. }
  271. static UA_StatusCode
  272. ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_String *customHostname) {
  273. UA_initialize_architecture_network();
  274. ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
  275. /* Get the discovery url from the hostname */
  276. UA_String du = UA_STRING_NULL;
  277. char discoveryUrlBuffer[256];
  278. char hostnameBuffer[256];
  279. if (customHostname->length) {
  280. du.length = (size_t)UA_snprintf(discoveryUrlBuffer, 255, "opc.tcp://%.*s:%d/",
  281. (int)customHostname->length,
  282. customHostname->data,
  283. layer->port);
  284. du.data = (UA_Byte*)discoveryUrlBuffer;
  285. }else{
  286. if(UA_gethostname(hostnameBuffer, 255) == 0) {
  287. du.length = (size_t)UA_snprintf(discoveryUrlBuffer, 255, "opc.tcp://%s:%d/",
  288. hostnameBuffer, layer->port);
  289. du.data = (UA_Byte*)discoveryUrlBuffer;
  290. } else {
  291. UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK, "Could not get the hostname");
  292. }
  293. }
  294. UA_String_copy(&du, &nl->discoveryUrl);
  295. /* Get addrinfo of the server and create server sockets */
  296. char portno[6];
  297. UA_snprintf(portno, 6, "%d", layer->port);
  298. struct addrinfo hints, *res;
  299. memset(&hints, 0, sizeof hints);
  300. hints.ai_family = AF_UNSPEC;
  301. hints.ai_socktype = SOCK_STREAM;
  302. hints.ai_flags = AI_PASSIVE;
  303. hints.ai_protocol = IPPROTO_TCP;
  304. if(UA_getaddrinfo(NULL, portno, &hints, &res) != 0)
  305. return UA_STATUSCODE_BADINTERNALERROR;
  306. /* There might be serveral addrinfos (for different network cards,
  307. * IPv4/IPv6). Add a server socket for all of them. */
  308. struct addrinfo *ai = res;
  309. for(layer->serverSocketsSize = 0;
  310. layer->serverSocketsSize < FD_SETSIZE && ai != NULL;
  311. ai = ai->ai_next)
  312. addServerSocket(layer, ai);
  313. UA_freeaddrinfo(res);
  314. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  315. "TCP network layer listening on %.*s",
  316. (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
  317. return UA_STATUSCODE_GOOD;
  318. }
  319. /* After every select, reset the sockets to listen on */
  320. static UA_Int32
  321. setFDSet(ServerNetworkLayerTCP *layer, fd_set *fdset) {
  322. FD_ZERO(fdset);
  323. UA_Int32 highestfd = 0;
  324. for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
  325. UA_fd_set(layer->serverSockets[i], fdset);
  326. if((UA_Int32)layer->serverSockets[i] > highestfd)
  327. highestfd = (UA_Int32)layer->serverSockets[i];
  328. }
  329. ConnectionEntry *e;
  330. LIST_FOREACH(e, &layer->connections, pointers) {
  331. UA_fd_set(e->connection.sockfd, fdset);
  332. if((UA_Int32)e->connection.sockfd > highestfd)
  333. highestfd = (UA_Int32)e->connection.sockfd;
  334. }
  335. return highestfd;
  336. }
  337. static UA_StatusCode
  338. ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
  339. UA_UInt16 timeout) {
  340. /* Every open socket can generate two jobs */
  341. ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
  342. if (layer->serverSocketsSize == 0)
  343. return UA_STATUSCODE_GOOD;
  344. /* Listen on open sockets (including the server) */
  345. fd_set fdset, errset;
  346. UA_Int32 highestfd = setFDSet(layer, &fdset);
  347. setFDSet(layer, &errset);
  348. struct timeval tmptv = {0, timeout * 1000};
  349. if (UA_select(highestfd+1, &fdset, NULL, &errset, &tmptv) < 0) {
  350. UA_LOG_SOCKET_ERRNO_WRAP(
  351. UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
  352. "Socket select failed with %s", errno_str));
  353. // we will retry, so do not return bad
  354. return UA_STATUSCODE_GOOD;
  355. }
  356. /* Accept new connections via the server sockets */
  357. for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
  358. if(!UA_fd_isset(layer->serverSockets[i], &fdset))
  359. continue;
  360. struct sockaddr_storage remote;
  361. socklen_t remote_size = sizeof(remote);
  362. UA_SOCKET newsockfd = UA_accept((UA_SOCKET)layer->serverSockets[i],
  363. (struct sockaddr*)&remote, &remote_size);
  364. if(newsockfd == UA_INVALID_SOCKET)
  365. continue;
  366. UA_LOG_TRACE(layer->logger, UA_LOGCATEGORY_NETWORK,
  367. "Connection %i | New TCP connection on server socket %i",
  368. (int)newsockfd, layer->serverSockets[i]);
  369. ServerNetworkLayerTCP_add(nl, layer, (UA_Int32)newsockfd, &remote);
  370. }
  371. /* Read from established sockets */
  372. ConnectionEntry *e, *e_tmp;
  373. UA_DateTime now = UA_DateTime_nowMonotonic();
  374. LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
  375. if ((e->connection.state == UA_CONNECTION_OPENING) &&
  376. (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_DATETIME_MSEC)))){
  377. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  378. "Connection %i | Closed by the server (no Hello Message)",
  379. e->connection.sockfd);
  380. LIST_REMOVE(e, pointers);
  381. UA_close(e->connection.sockfd);
  382. UA_Server_removeConnection(server, &e->connection);
  383. continue;
  384. }
  385. if(!UA_fd_isset(e->connection.sockfd, &errset) &&
  386. !UA_fd_isset(e->connection.sockfd, &fdset))
  387. continue;
  388. UA_LOG_TRACE(layer->logger, UA_LOGCATEGORY_NETWORK,
  389. "Connection %i | Activity on the socket",
  390. e->connection.sockfd);
  391. UA_ByteString buf = UA_BYTESTRING_NULL;
  392. UA_StatusCode retval = connection_recv(&e->connection, &buf, 0);
  393. if(retval == UA_STATUSCODE_GOOD) {
  394. /* Process packets */
  395. UA_Server_processBinaryMessage(server, &e->connection, &buf);
  396. connection_releaserecvbuffer(&e->connection, &buf);
  397. } else if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
  398. /* The socket is shutdown but not closed */
  399. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  400. "Connection %i | Closed",
  401. e->connection.sockfd);
  402. LIST_REMOVE(e, pointers);
  403. UA_close(e->connection.sockfd);
  404. UA_Server_removeConnection(server, &e->connection);
  405. }
  406. }
  407. return UA_STATUSCODE_GOOD;
  408. }
  409. static void
  410. ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
  411. ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
  412. UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
  413. "Shutting down the TCP network layer");
  414. /* Close the server sockets */
  415. for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
  416. UA_shutdown(layer->serverSockets[i], 2);
  417. UA_close(layer->serverSockets[i]);
  418. }
  419. layer->serverSocketsSize = 0;
  420. /* Close open connections */
  421. ConnectionEntry *e;
  422. LIST_FOREACH(e, &layer->connections, pointers)
  423. ServerNetworkLayerTCP_close(&e->connection);
  424. /* Run recv on client sockets. This picks up the closed sockets and frees
  425. * the connection. */
  426. ServerNetworkLayerTCP_listen(nl, server, 0);
  427. UA_deinitialize_architecture_network();
  428. }
  429. /* run only when the server is stopped */
  430. static void
  431. ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) {
  432. ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
  433. UA_String_deleteMembers(&nl->discoveryUrl);
  434. /* Hard-close and remove remaining connections. The server is no longer
  435. * running. So this is safe. */
  436. ConnectionEntry *e, *e_tmp;
  437. LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
  438. LIST_REMOVE(e, pointers);
  439. UA_close(e->connection.sockfd);
  440. UA_free(e);
  441. }
  442. /* Free the layer */
  443. UA_free(layer);
  444. }
  445. UA_ServerNetworkLayer
  446. UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port, UA_Logger logger) {
  447. UA_ServerNetworkLayer nl;
  448. memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
  449. ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP*)
  450. UA_calloc(1,sizeof(ServerNetworkLayerTCP));
  451. if(!layer)
  452. return nl;
  453. layer->logger = (logger != NULL ? logger : UA_Log_Stdout);
  454. layer->port = port;
  455. nl.handle = layer;
  456. nl.localConnectionConfig = config;
  457. nl.start = ServerNetworkLayerTCP_start;
  458. nl.listen = ServerNetworkLayerTCP_listen;
  459. nl.stop = ServerNetworkLayerTCP_stop;
  460. nl.deleteMembers = ServerNetworkLayerTCP_deleteMembers;
  461. return nl;
  462. }
  463. typedef struct TCPClientConnection {
  464. struct addrinfo hints, *server;
  465. UA_DateTime connStart;
  466. char* endpointURL;
  467. UA_UInt32 timeout;
  468. } TCPClientConnection;
  469. /***************************/
  470. /* Client NetworkLayer TCP */
  471. /***************************/
  472. static void
  473. ClientNetworkLayerTCP_close(UA_Connection *connection) {
  474. if (connection->state == UA_CONNECTION_CLOSED)
  475. return;
  476. UA_shutdown(connection->sockfd, 2);
  477. UA_close(connection->sockfd);
  478. connection->state = UA_CONNECTION_CLOSED;
  479. }
  480. static void
  481. ClientNetworkLayerTCP_free(UA_Connection *connection) {
  482. if (connection->handle){
  483. TCPClientConnection *tcpConnection = (TCPClientConnection *)connection->handle;
  484. if(tcpConnection->server)
  485. UA_freeaddrinfo(tcpConnection->server);
  486. UA_free(tcpConnection);
  487. }
  488. }
  489. UA_StatusCode UA_ClientConnectionTCP_poll(UA_Client *client, void *data) {
  490. UA_Connection *connection = (UA_Connection*) data;
  491. if (connection->state == UA_CONNECTION_CLOSED)
  492. return UA_STATUSCODE_BADDISCONNECT;
  493. TCPClientConnection *tcpConnection =
  494. (TCPClientConnection*) connection->handle;
  495. UA_DateTime connStart = UA_DateTime_nowMonotonic();
  496. UA_SOCKET clientsockfd;
  497. if (connection->state == UA_CONNECTION_ESTABLISHED) {
  498. UA_Client_removeRepeatedCallback(client, connection->connectCallbackID);
  499. connection->connectCallbackID = 0;
  500. return UA_STATUSCODE_GOOD;
  501. }
  502. if ((UA_Double) (UA_DateTime_nowMonotonic() - tcpConnection->connStart)
  503. > tcpConnection->timeout* UA_DATETIME_MSEC ) {
  504. // connection timeout
  505. ClientNetworkLayerTCP_close(connection);
  506. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  507. "Timed out");
  508. return UA_STATUSCODE_BADDISCONNECT;
  509. }
  510. /* On linux connect may immediately return with ECONNREFUSED but we still want to try to connect */
  511. /* Thus use a loop and retry until timeout is reached */
  512. /* Get a socket */
  513. clientsockfd = UA_socket(tcpConnection->server->ai_family,
  514. tcpConnection->server->ai_socktype,
  515. tcpConnection->server->ai_protocol);
  516. connection->sockfd = (UA_Int32) clientsockfd; /* cast for win32 */
  517. if(clientsockfd == UA_INVALID_SOCKET) {
  518. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  519. "Could not create client socket: %s", strerror(UA_ERRNO));
  520. ClientNetworkLayerTCP_close(connection);
  521. return UA_STATUSCODE_BADDISCONNECT;
  522. }
  523. /* Non blocking connect to be able to timeout */
  524. if (UA_socket_set_nonblocking(clientsockfd) != UA_STATUSCODE_GOOD) {
  525. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  526. "Could not set the client socket to nonblocking");
  527. ClientNetworkLayerTCP_close(connection);
  528. return UA_STATUSCODE_BADDISCONNECT;
  529. }
  530. /* Non blocking connect */
  531. int error = UA_connect(clientsockfd, tcpConnection->server->ai_addr,
  532. tcpConnection->server->ai_addrlen);
  533. if ((error == -1) && (UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
  534. ClientNetworkLayerTCP_close(connection);
  535. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  536. "Connection to failed with error: %s", strerror(UA_ERRNO));
  537. return UA_STATUSCODE_BADDISCONNECT;
  538. }
  539. /* Use select to wait and check if connected */
  540. if (error == -1 && (UA_ERRNO == UA_ERR_CONNECTION_PROGRESS)) {
  541. /* connection in progress. Wait until connected using select */
  542. UA_UInt32 timeSinceStart =
  543. (UA_UInt32) ((UA_Double) (UA_DateTime_nowMonotonic() - connStart)
  544. * UA_DATETIME_MSEC);
  545. #ifdef _OS9000
  546. /* OS-9 can't use select for checking write sockets.
  547. * Therefore, we need to use connect until success or failed
  548. */
  549. UA_UInt32 timeout_usec = (tcpConnection->timeout - timeSinceStart)
  550. * 1000;
  551. int resultsize = 0;
  552. do {
  553. u_int32 time = 0x80000001;
  554. signal_code sig;
  555. timeout_usec -= 1000000/256; // Sleep 1/256 second
  556. if (timeout_usec < 0)
  557. break;
  558. _os_sleep(&time,&sig);
  559. error = connect(clientsockfd, tcpConnection->server->ai_addr,
  560. tcpConnection->server->ai_addrlen);
  561. if ((error == -1 && errno == EISCONN) || (error == 0))
  562. resultsize = 1;
  563. if (error == -1 && errno != EALREADY && errno != EINPROGRESS)
  564. break;
  565. }
  566. while(resultsize == 0);
  567. #else
  568. fd_set fdset;
  569. FD_ZERO(&fdset);
  570. UA_fd_set(clientsockfd, &fdset);
  571. UA_UInt32 timeout_usec = (tcpConnection->timeout - timeSinceStart)
  572. * 1000;
  573. struct timeval tmptv = { (long int) (timeout_usec / 1000000),
  574. (long int) (timeout_usec % 1000000) };
  575. int resultsize = UA_select((UA_Int32) (clientsockfd + 1), NULL, &fdset,
  576. NULL, &tmptv);
  577. #endif
  578. if (resultsize == 1) {
  579. /* Windows does not have any getsockopt equivalent and it is not needed there */
  580. #ifdef _WIN32
  581. connection->sockfd = clientsockfd;
  582. connection->state = UA_CONNECTION_ESTABLISHED;
  583. return UA_STATUSCODE_GOOD;
  584. #else
  585. OPTVAL_TYPE so_error;
  586. socklen_t len = sizeof so_error;
  587. int ret = UA_getsockopt(clientsockfd, SOL_SOCKET, SO_ERROR, &so_error,
  588. &len);
  589. if (ret != 0 || so_error != 0) {
  590. /* on connection refused we should still try to connect */
  591. /* connection refused happens on localhost or local ip without timeout */
  592. if (so_error != ECONNREFUSED) {
  593. // general error
  594. ClientNetworkLayerTCP_close(connection);
  595. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  596. "Connection to failed with error: %s",
  597. strerror(ret == 0 ? so_error : UA_ERRNO));
  598. return UA_STATUSCODE_BADDISCONNECT;
  599. }
  600. /* wait until we try a again. Do not make this too small, otherwise the
  601. * timeout is somehow wrong */
  602. } else {
  603. connection->state = UA_CONNECTION_ESTABLISHED;
  604. return UA_STATUSCODE_GOOD;
  605. }
  606. #endif
  607. }
  608. } else {
  609. connection->state = UA_CONNECTION_ESTABLISHED;
  610. return UA_STATUSCODE_GOOD;
  611. }
  612. #ifdef SO_NOSIGPIPE
  613. int val = 1;
  614. int sso_result = setsockopt(connection->sockfd, SOL_SOCKET,
  615. SO_NOSIGPIPE, (void*)&val, sizeof(val));
  616. if(sso_result < 0)
  617. UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
  618. "Couldn't set SO_NOSIGPIPE");
  619. #endif
  620. return UA_STATUSCODE_GOOD;
  621. }
  622. UA_Connection UA_ClientConnectionTCP_init(UA_ConnectionConfig config,
  623. const char *endpointUrl, const UA_UInt32 timeout,
  624. UA_Logger logger) {
  625. UA_Connection connection;
  626. memset(&connection, 0, sizeof(UA_Connection));
  627. connection.state = UA_CONNECTION_OPENING;
  628. connection.config = config;
  629. connection.send = connection_write;
  630. connection.recv = connection_recv;
  631. connection.close = ClientNetworkLayerTCP_close;
  632. connection.free = ClientNetworkLayerTCP_free;
  633. connection.getSendBuffer = connection_getsendbuffer;
  634. connection.releaseSendBuffer = connection_releasesendbuffer;
  635. connection.releaseRecvBuffer = connection_releaserecvbuffer;
  636. TCPClientConnection *tcpClientConnection = (TCPClientConnection*) UA_malloc(
  637. sizeof(TCPClientConnection));
  638. connection.handle = (void*) tcpClientConnection;
  639. tcpClientConnection->timeout = timeout;
  640. UA_String endpointUrlString = UA_STRING((char*) (uintptr_t) endpointUrl);
  641. UA_String hostnameString = UA_STRING_NULL;
  642. UA_String pathString = UA_STRING_NULL;
  643. UA_UInt16 port = 0;
  644. char hostname[512];
  645. tcpClientConnection->connStart = UA_DateTime_nowMonotonic();
  646. UA_StatusCode parse_retval = UA_parseEndpointUrl(&endpointUrlString,
  647. &hostnameString, &port, &pathString);
  648. if (parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
  649. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  650. "Server url is invalid: %s", endpointUrl);
  651. return connection;
  652. }
  653. memcpy(hostname, hostnameString.data, hostnameString.length);
  654. hostname[hostnameString.length] = 0;
  655. if (port == 0) {
  656. port = 4840;
  657. UA_LOG_INFO(logger, UA_LOGCATEGORY_NETWORK,
  658. "No port defined, using default port %d", port);
  659. }
  660. memset(&tcpClientConnection->hints, 0, sizeof(tcpClientConnection->hints));
  661. tcpClientConnection->hints.ai_family = AF_UNSPEC;
  662. tcpClientConnection->hints.ai_socktype = SOCK_STREAM;
  663. char portStr[6];
  664. UA_snprintf(portStr, 6, "%d", port);
  665. int error = UA_getaddrinfo(hostname, portStr, &tcpClientConnection->hints,
  666. &tcpClientConnection->server);
  667. if (error != 0 || !tcpClientConnection->server) {
  668. UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  669. "DNS lookup of %s failed with error %s", hostname, errno_str));
  670. return connection;
  671. }
  672. return connection;
  673. }
  674. UA_Connection
  675. UA_ClientConnectionTCP(UA_ConnectionConfig config,
  676. const char *endpointUrl, const UA_UInt32 timeout,
  677. UA_Logger logger) {
  678. UA_initialize_architecture_network();
  679. if(logger == NULL) {
  680. logger = UA_Log_Stdout;
  681. }
  682. UA_Connection connection;
  683. memset(&connection, 0, sizeof(UA_Connection));
  684. connection.state = UA_CONNECTION_CLOSED;
  685. connection.config = config;
  686. connection.send = connection_write;
  687. connection.recv = connection_recv;
  688. connection.close = ClientNetworkLayerTCP_close;
  689. connection.free = ClientNetworkLayerTCP_free;
  690. connection.getSendBuffer = connection_getsendbuffer;
  691. connection.releaseSendBuffer = connection_releasesendbuffer;
  692. connection.releaseRecvBuffer = connection_releaserecvbuffer;
  693. connection.handle = NULL;
  694. UA_String endpointUrlString = UA_STRING((char*)(uintptr_t)endpointUrl);
  695. UA_String hostnameString = UA_STRING_NULL;
  696. UA_String pathString = UA_STRING_NULL;
  697. UA_UInt16 port = 0;
  698. char hostname[512];
  699. UA_StatusCode parse_retval =
  700. UA_parseEndpointUrl(&endpointUrlString, &hostnameString,
  701. &port, &pathString);
  702. if(parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
  703. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  704. "Server url is invalid: %s", endpointUrl);
  705. return connection;
  706. }
  707. memcpy(hostname, hostnameString.data, hostnameString.length);
  708. hostname[hostnameString.length] = 0;
  709. if(port == 0) {
  710. port = 4840;
  711. UA_LOG_INFO(logger, UA_LOGCATEGORY_NETWORK,
  712. "No port defined, using default port %d", port);
  713. }
  714. struct addrinfo hints, *server;
  715. memset(&hints, 0, sizeof(hints));
  716. hints.ai_family = AF_UNSPEC;
  717. hints.ai_socktype = SOCK_STREAM;
  718. hints.ai_protocol = IPPROTO_TCP;
  719. char portStr[6];
  720. UA_snprintf(portStr, 6, "%d", port);
  721. int error = UA_getaddrinfo(hostname, portStr, &hints, &server);
  722. if(error != 0 || !server) {
  723. UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  724. "DNS lookup of %s failed with error %s", hostname, errno_str));
  725. return connection;
  726. }
  727. UA_Boolean connected = UA_FALSE;
  728. UA_DateTime dtTimeout = timeout * UA_DATETIME_MSEC;
  729. UA_DateTime connStart = UA_DateTime_nowMonotonic();
  730. UA_SOCKET clientsockfd;
  731. /* On linux connect may immediately return with ECONNREFUSED but we still
  732. * want to try to connect. So use a loop and retry until timeout is
  733. * reached. */
  734. do {
  735. /* Get a socket */
  736. clientsockfd = UA_socket(server->ai_family,
  737. server->ai_socktype,
  738. server->ai_protocol);
  739. if(clientsockfd == UA_INVALID_SOCKET) {
  740. UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  741. "Could not create client socket: %s", errno_str));
  742. UA_freeaddrinfo(server);
  743. return connection;
  744. }
  745. connection.state = UA_CONNECTION_OPENING;
  746. /* Connect to the server */
  747. connection.sockfd = clientsockfd;
  748. /* Non blocking connect to be able to timeout */
  749. if (UA_socket_set_nonblocking(clientsockfd) != UA_STATUSCODE_GOOD) {
  750. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  751. "Could not set the client socket to nonblocking");
  752. ClientNetworkLayerTCP_close(&connection);
  753. UA_freeaddrinfo(server);
  754. return connection;
  755. }
  756. /* Non blocking connect */
  757. error = UA_connect(clientsockfd, server->ai_addr, (socklen_t)server->ai_addrlen);
  758. if ((error == -1) && (UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
  759. ClientNetworkLayerTCP_close(&connection);
  760. UA_LOG_SOCKET_ERRNO_WRAP(
  761. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  762. "Connection to %s failed with error: %s",
  763. endpointUrl, errno_str));
  764. UA_freeaddrinfo(server);
  765. return connection;
  766. }
  767. /* Use select to wait and check if connected */
  768. if (error == -1 && (UA_ERRNO == UA_ERR_CONNECTION_PROGRESS)) {
  769. /* connection in progress. Wait until connected using select */
  770. UA_DateTime timeSinceStart = UA_DateTime_nowMonotonic() - connStart;
  771. if(timeSinceStart > dtTimeout)
  772. break;
  773. #ifdef _OS9000
  774. /* OS-9 can't use select for checking write sockets.
  775. * Therefore, we need to use connect until success or failed
  776. */
  777. UA_DateTime timeout_usec = (dtTimeout - timeSinceStart) / UA_DATETIME_USEC;
  778. int resultsize = 0;
  779. do {
  780. u_int32 time = 0x80000001;
  781. signal_code sig;
  782. timeout_usec -= 1000000/256; // Sleep 1/256 second
  783. if (timeout_usec < 0)
  784. break;
  785. _os_sleep(&time,&sig);
  786. error = connect(clientsockfd, server->ai_addr, server->ai_addrlen);
  787. if ((error == -1 && errno == EISCONN) || (error == 0))
  788. resultsize = 1;
  789. if (error == -1 && errno != EALREADY && errno != EINPROGRESS)
  790. break;
  791. }
  792. while(resultsize == 0);
  793. #else
  794. fd_set fdset;
  795. FD_ZERO(&fdset);
  796. UA_fd_set(clientsockfd, &fdset);
  797. UA_DateTime timeout_usec = (dtTimeout - timeSinceStart) / UA_DATETIME_USEC;
  798. struct timeval tmptv = {(long int) (timeout_usec / 1000000),
  799. (long int) (timeout_usec % 1000000)};
  800. int resultsize = UA_select((UA_Int32)(clientsockfd + 1), NULL, &fdset, NULL, &tmptv);
  801. #endif
  802. if(resultsize == 1) {
  803. #ifdef _WIN32
  804. /* Windows does not have any getsockopt equivalent and it is not
  805. * needed there */
  806. connected = true;
  807. break;
  808. #else
  809. OPTVAL_TYPE so_error;
  810. socklen_t len = sizeof so_error;
  811. int ret = UA_getsockopt(clientsockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
  812. if (ret != 0 || so_error != 0) {
  813. /* on connection refused we should still try to connect */
  814. /* connection refused happens on localhost or local ip without timeout */
  815. if (so_error != ECONNREFUSED) {
  816. ClientNetworkLayerTCP_close(&connection);
  817. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  818. "Connection to %s failed with error: %s",
  819. endpointUrl, strerror(ret == 0 ? so_error : UA_ERRNO));
  820. UA_freeaddrinfo(server);
  821. return connection;
  822. }
  823. /* wait until we try a again. Do not make this too small, otherwise the
  824. * timeout is somehow wrong */
  825. UA_sleep_ms(100);
  826. } else {
  827. connected = true;
  828. break;
  829. }
  830. #endif
  831. }
  832. } else {
  833. connected = true;
  834. break;
  835. }
  836. ClientNetworkLayerTCP_close(&connection);
  837. } while ((UA_DateTime_nowMonotonic() - connStart) < dtTimeout);
  838. UA_freeaddrinfo(server);
  839. if(!connected) {
  840. /* connection timeout */
  841. if (connection.state != UA_CONNECTION_CLOSED)
  842. ClientNetworkLayerTCP_close(&connection);
  843. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  844. "Trying to connect to %s timed out",
  845. endpointUrl);
  846. return connection;
  847. }
  848. /* We are connected. Reset socket to blocking */
  849. if(UA_socket_set_blocking(clientsockfd) != UA_STATUSCODE_GOOD) {
  850. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  851. "Could not set the client socket to blocking");
  852. ClientNetworkLayerTCP_close(&connection);
  853. return connection;
  854. }
  855. #ifdef SO_NOSIGPIPE
  856. int val = 1;
  857. int sso_result = UA_setsockopt(connection.sockfd, SOL_SOCKET,
  858. SO_NOSIGPIPE, (void*)&val, sizeof(val));
  859. if(sso_result < 0)
  860. UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
  861. "Couldn't set SO_NOSIGPIPE");
  862. #endif
  863. return connection;
  864. }