PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/cutil/src/socket.c

https://bitbucket.org/huseby_linden/cllsd
C | 1378 lines | 1056 code | 206 blank | 116 comment | 97 complexity | c52d1f70dd50625b865f38b23158c222 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 2 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU Library General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <stdint.h>
  19. #include <string.h>
  20. #include <assert.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24. #include <netdb.h>
  25. #include <poll.h>
  26. #include <arpa/inet.h>
  27. #include <netinet/in.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31. #include <sys/uio.h>
  32. #include <sys/un.h>
  33. #include <netinet/tcp.h>
  34. #include "debug.h"
  35. #include "macros.h"
  36. #include "events.h"
  37. #include "list.h"
  38. #include "socket.h"
  39. #if defined(UNIT_TESTING)
  40. #include "test_flags.h"
  41. extern evt_loop_t * el;
  42. #endif
  43. struct socket_s
  44. {
  45. socket_type_t type; /* type of socket */
  46. int32_t connected; /* is the socket connected? */
  47. int32_t bound; /* is the socket bound? */
  48. int8_t* host; /* host name */
  49. uint16_t port; /* port number */
  50. IPv4 addr; /* IPv4 struct from host string */
  51. void * user_data; /* passed to ops callbacks */
  52. socket_ops_t ops; /* socket callbacks */
  53. aiofd_t aiofd; /* the fd management state */
  54. };
  55. static int socket_get_error( socket_t * const s, int * errval )
  56. {
  57. socklen_t len = sizeof(int);
  58. CHECK_PTR_RET( s, FALSE );
  59. CHECK_PTR_RET( errval, FALSE );
  60. #if defined(UNIT_TESTING)
  61. if ( fake_socket_getsockopt )
  62. {
  63. *errval = fake_socket_errval;
  64. return fake_socket_get_error_ret;
  65. }
  66. #endif
  67. CHECK_RET( getsockopt( s->aiofd.wfd, SOL_SOCKET, SO_ERROR, errval, &len ) < 0, TRUE );
  68. return FALSE;
  69. }
  70. static int socket_do_tcp_bind( socket_t * const s )
  71. {
  72. int len = 0;
  73. struct sockaddr_in in_addr;
  74. #if defined(UNIT_TESTING)
  75. CHECK_RET( !fake_socket_bind, fake_socket_bind_ret );
  76. #endif
  77. CHECK_PTR_RET( s, FALSE );
  78. CHECK_RET( s->type == SOCKET_TCP, FALSE );
  79. CHECK_RET( s->port > 0, FALSE );
  80. /* initialize the socket address struct */
  81. MEMSET( &in_addr, 0, sizeof(struct sockaddr_in) );
  82. in_addr.sin_family = AF_INET;
  83. in_addr.sin_addr.s_addr = s->addr.s_addr;
  84. in_addr.sin_port = htons(s->port);
  85. len = sizeof( in_addr );
  86. if ( BIND( s->aiofd.rfd, (struct sockaddr*)&in_addr, len) < 0 )
  87. {
  88. DEBUG( "failed to bind (errno: %d)\n", errno );
  89. return FALSE;
  90. }
  91. return TRUE;
  92. }
  93. static int socket_do_unix_bind( socket_t * const s )
  94. {
  95. int len = 0;
  96. struct sockaddr_un un_addr;
  97. #if defined(UNIT_TESTING)
  98. CHECK_RET( !fake_socket_bind, fake_socket_bind_ret );
  99. #endif
  100. CHECK_PTR_RET( s, FALSE );
  101. CHECK_RET( s->type == SOCKET_UNIX, FALSE );
  102. CHECK_PTR_RET( s->host, FALSE );
  103. /* initialize the socket address struct */
  104. MEMSET( &un_addr, 0, sizeof(struct sockaddr_un) );
  105. un_addr.sun_family = AF_UNIX;
  106. strncpy( un_addr.sun_path, s->host, 100 );
  107. /* try to delete the socket inode */
  108. unlink( un_addr.sun_path );
  109. /* calculate the length of the address struct */
  110. len = strlen( un_addr.sun_path ) + sizeof( un_addr.sun_family );
  111. if ( BIND( s->aiofd.rfd, (struct sockaddr*)&un_addr, len) < 0 )
  112. {
  113. DEBUG( "failed to bind (errno: %d)\n", errno );
  114. return FALSE;
  115. }
  116. return TRUE;
  117. }
  118. static int socket_do_tcp_connect( socket_t * const s )
  119. {
  120. int len = 0;
  121. struct sockaddr_in in_addr;
  122. #if defined(UNIT_TESTING)
  123. CHECK_RET( !fake_socket_connect, fake_socket_connect_ret );
  124. #endif
  125. CHECK_PTR_RET( s, FALSE );
  126. CHECK_RET( s->type == SOCKET_TCP, FALSE );
  127. CHECK_RET( s->port > 0, FALSE );
  128. /* initialize the socket address struct */
  129. MEMSET( &in_addr, 0, sizeof(struct sockaddr_in) );
  130. in_addr.sin_family = AF_INET;
  131. in_addr.sin_addr.s_addr = s->addr.s_addr;
  132. in_addr.sin_port = htons(s->port);
  133. len = sizeof( in_addr );
  134. /* try to make the connection */
  135. if ( CONNECT(s->aiofd.rfd, (struct sockaddr*)&in_addr, len) < 0 )
  136. {
  137. if ( ERRNO == EINPROGRESS )
  138. {
  139. DEBUG( "connection in progress\n" );
  140. }
  141. else
  142. {
  143. DEBUG("failed to initiate connect to the server\n");
  144. return FALSE;
  145. }
  146. }
  147. return TRUE;
  148. }
  149. static int socket_do_unix_connect( socket_t * const s )
  150. {
  151. int len = 0;
  152. struct sockaddr_un un_addr;
  153. #if defined(UNIT_TESTING)
  154. CHECK_RET( !fake_socket_connect, fake_socket_connect_ret );
  155. #endif
  156. CHECK_PTR_RET( s, FALSE );
  157. CHECK_RET( s->type == SOCKET_UNIX, FALSE );
  158. CHECK_PTR_RET( s->host, FALSE );
  159. /* initialize the socket address struct */
  160. MEMSET( &un_addr, 0, sizeof(struct sockaddr_un) );
  161. un_addr.sun_family = AF_UNIX;
  162. strncpy( un_addr.sun_path, s->host, 100 );
  163. /* calculate the length of the address struct */
  164. len = strlen( un_addr.sun_path ) + sizeof( un_addr.sun_family );
  165. /* try to make the connection */
  166. if ( CONNECT(s->aiofd.rfd, (struct sockaddr*)&un_addr, len) < 0 )
  167. {
  168. if ( ERRNO == EINPROGRESS )
  169. {
  170. DEBUG( "connection in progress\n" );
  171. }
  172. else
  173. {
  174. DEBUG("failed to initiate connect to the server\n");
  175. return FALSE;
  176. }
  177. }
  178. return TRUE;
  179. }
  180. static socket_ret_t socket_lookup_host( socket_t * const s,
  181. int8_t const * const hostname)
  182. {
  183. struct hostent *host;
  184. #if defined(UNIT_TESTING)
  185. CHECK_RET( !fake_socket_lookup_host, fake_socket_lookup_host_ret );
  186. #endif
  187. CHECK_PTR_RET(s, SOCKET_BADPARAM);
  188. CHECK_RET((hostname != NULL) || (s->host != NULL), SOCKET_BADHOSTNAME);
  189. /* store the hostname if needed */
  190. if( hostname != NULL )
  191. {
  192. /* free the existing host if any */
  193. FREE(s->host);
  194. /* copy the hostname into the server struct */
  195. s->host = T(strdup((char const * const)hostname));
  196. }
  197. if ( s->type != SOCKET_UNIX )
  198. {
  199. /* try to look up the host name */
  200. if( (host = gethostbyname((char const * const)hostname)) == NULL )
  201. {
  202. DEBUG("look up of %s failed\n", hostname);
  203. return SOCKET_BADHOSTNAME;
  204. }
  205. /* store the IP address */
  206. s->addr.s_addr = *((uint32_t*)host->h_addr_list[0]);
  207. }
  208. return SOCKET_OK;
  209. }
  210. static int socket_aiofd_write_fn( aiofd_t * const aiofd,
  211. uint8_t const * const buffer,
  212. void * user_data )
  213. {
  214. int errval = 0;
  215. socket_t * s = (socket_t*)user_data;
  216. CHECK_PTR_RET( aiofd, FALSE );
  217. CHECK_PTR_RET( s, FALSE );
  218. if ( s->connected )
  219. {
  220. if ( buffer == NULL )
  221. {
  222. if ( list_count( &(s->aiofd.wbuf) ) == 0 )
  223. {
  224. /* stop the write event processing until we have data to write */
  225. return FALSE;
  226. }
  227. /* this will keep the write event processing going */
  228. return TRUE;
  229. }
  230. else
  231. {
  232. /* call the write complete callback to let client know that a particular
  233. * buffer has been written to the socket. */
  234. if ( s->ops.write_fn != NULL )
  235. {
  236. DEBUG( "calling socket write complete callback\n" );
  237. (*(s->ops.write_fn))( s, buffer, s->user_data );
  238. }
  239. return TRUE;
  240. }
  241. }
  242. else if ( s->aiofd.rfd != -1 )
  243. {
  244. /* we're connecting the socket and this write event callback is to signal
  245. * that the connect has completed either successfully or failed */
  246. /* check to see if the connect() succeeded */
  247. if ( !socket_get_error( s, &errval ) )
  248. {
  249. DEBUG( "failed to get socket option while checking connect\n" );
  250. if ( s->ops.error_fn != NULL )
  251. {
  252. DEBUG( "calling socket error callback\n" );
  253. (*(s->ops.error_fn))( s, errno, s->user_data );
  254. }
  255. /* stop write event processing */
  256. return FALSE;
  257. }
  258. if ( errval == 0 )
  259. {
  260. DEBUG( "socket connected\n" );
  261. s->connected = TRUE;
  262. if ( s->ops.connect_fn != NULL )
  263. {
  264. DEBUG( "calling socket connect callback\n" );
  265. /* call the connect callback */
  266. (*(s->ops.connect_fn))( s, s->user_data );
  267. }
  268. /* we're connected to start read event */
  269. /* TODO: check for error and handle it properly */
  270. aiofd_enable_read_evt( &(s->aiofd), TRUE );
  271. if ( list_count( &(s->aiofd.wbuf) ) == 0 )
  272. {
  273. /* stop the write event processing until we have data to write */
  274. return FALSE;
  275. }
  276. /* this will keep the write event processing going */
  277. return TRUE;
  278. }
  279. else
  280. {
  281. DEBUG( "socket connect failed\n" );
  282. if ( s->ops.error_fn != NULL )
  283. {
  284. DEBUG( "calling socket error callback\n" );
  285. (*(s->ops.error_fn))( s, errno, s->user_data );
  286. }
  287. /* stop write event processing */
  288. return FALSE;
  289. }
  290. }
  291. return TRUE;
  292. }
  293. static int socket_aiofd_error_fn( aiofd_t * const aiofd,
  294. int err,
  295. void * user_data )
  296. {
  297. socket_t * s = (socket_t*)user_data;
  298. CHECK_PTR_RET( aiofd, FALSE );
  299. CHECK_PTR_RET( s, FALSE );
  300. if ( s->ops.error_fn != NULL )
  301. {
  302. DEBUG( "calling socket error callback\n" );
  303. (*(s->ops.error_fn))( s, errno, s->user_data );
  304. }
  305. return TRUE;
  306. }
  307. static int socket_aiofd_read_fn( aiofd_t * const aiofd,
  308. size_t const nread,
  309. void * user_data )
  310. {
  311. socket_t * s = (socket_t*)user_data;
  312. CHECK_PTR_RET( aiofd, FALSE );
  313. CHECK_PTR_RET( s, FALSE );
  314. if ( socket_is_bound( s ) )
  315. {
  316. /* this is a socket accepting incoming connections */
  317. if ( s->ops.connect_fn != NULL )
  318. {
  319. DEBUG( "calling socket connect callback for incoming connection\n" );
  320. if ( (*(s->ops.connect_fn))( s, s->user_data ) != SOCKET_OK )
  321. {
  322. DEBUG( "failed to accept incoming connection!\n" );
  323. }
  324. }
  325. }
  326. else
  327. {
  328. if ( nread == 0 )
  329. {
  330. /* the other side disconnected, so follow suit */
  331. socket_disconnect( s );
  332. /* return FALSE to turn off the read event processing */
  333. return FALSE;
  334. }
  335. /* this is a normal connection socket, so pass the read event along */
  336. if ( s->ops.read_fn != NULL )
  337. {
  338. DEBUG( "calling socket read callback\n");
  339. (*(s->ops.read_fn))( s, nread, s->user_data );
  340. }
  341. }
  342. return TRUE;
  343. }
  344. static int socket_initialize( socket_t * const s,
  345. socket_type_t const type,
  346. socket_ops_t * const ops,
  347. evt_loop_t * const el,
  348. void * user_data )
  349. {
  350. int fd;
  351. int32_t flags;
  352. static aiofd_ops_t aiofd_ops =
  353. {
  354. &socket_aiofd_read_fn,
  355. &socket_aiofd_write_fn,
  356. &socket_aiofd_error_fn
  357. };
  358. #if defined(UNIT_TESTING)
  359. CHECK_RET( !fail_socket_initialize, FALSE );
  360. #endif
  361. CHECK_PTR_RET( s, FALSE );
  362. CHECK_RET( VALID_SOCKET_TYPE( type ), FALSE );
  363. CHECK_PTR_RET( ops, FALSE );
  364. CHECK_PTR_RET( el, FALSE );
  365. MEMSET( (void*)s, 0, sizeof(socket_t) );
  366. /* store the type */
  367. s->type = type;
  368. /* store the user_data pointer */
  369. s->user_data = user_data;
  370. /* copy the ops into place */
  371. MEMCPY( (void*)&(s->ops), ops, sizeof(socket_ops_t) );
  372. /* do the connect based on the type */
  373. switch(s->type)
  374. {
  375. case SOCKET_TCP:
  376. /* try to open a socket */
  377. if ( (fd = SOCKET( PF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0 )
  378. {
  379. DEBUG("failed to open socket\n");
  380. return FALSE;
  381. }
  382. else
  383. {
  384. DEBUG("created socket\n");
  385. }
  386. /* turn off TCP naggle algorithm */
  387. flags = 1;
  388. if ( SETSOCKOPT( fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flags, sizeof(flags) ) )
  389. {
  390. DEBUG( "failed to turn on TCP no delay\n" );
  391. return FALSE;
  392. }
  393. else
  394. {
  395. DEBUG("turned on TCP no delay\n");
  396. }
  397. break;
  398. case SOCKET_UNIX:
  399. /* try to open a socket */
  400. if ( (fd = SOCKET( PF_UNIX, SOCK_STREAM, 0 )) < 0 )
  401. {
  402. DEBUG("failed to open socket\n");
  403. return FALSE;
  404. }
  405. else
  406. {
  407. DEBUG("created socket\n");
  408. }
  409. break;
  410. }
  411. /* set the socket to non blocking mode */
  412. flags = FCNTL( fd, F_GETFL );
  413. if( FCNTL( fd, F_SETFL, (flags | O_NONBLOCK) ) < 0 )
  414. {
  415. DEBUG("failed to set socket to non-blocking\n");
  416. }
  417. else
  418. {
  419. DEBUG("socket is now non-blocking\n");
  420. }
  421. /* initialize the aiofd to manage the socket */
  422. if ( aiofd_initialize( &(s->aiofd), fd, fd, &aiofd_ops, el, (void*)s ) == FALSE )
  423. {
  424. DEBUG( "failed to initialzie the aiofd\n" );
  425. return FALSE;
  426. }
  427. return TRUE;
  428. }
  429. socket_t* socket_new( socket_type_t const type,
  430. socket_ops_t * const ops,
  431. evt_loop_t * const el,
  432. void * user_data )
  433. {
  434. socket_ret_t ret = SOCKET_OK;
  435. socket_t* s = NULL;
  436. /* allocate the socket struct */
  437. s = CALLOC( 1, sizeof(socket_t) );
  438. CHECK_PTR_RET(s, NULL);
  439. /* initlialize the socket */
  440. if ( socket_initialize( s, type, ops, el, user_data ) == FALSE )
  441. {
  442. socket_delete( s );
  443. return NULL;
  444. }
  445. return s;
  446. }
  447. static void socket_deinitialize( socket_t * const s )
  448. {
  449. /* close the socket */
  450. if ( s->aiofd.rfd >= 0 )
  451. socket_disconnect( s );
  452. /* clean up the host name */
  453. if ( s->host != NULL )
  454. FREE ( s->host );
  455. }
  456. void socket_delete( void * s )
  457. {
  458. socket_t * sock = (socket_t*)s;
  459. CHECK_PTR( s );
  460. socket_deinitialize( sock );
  461. FREE( sock );
  462. }
  463. /* check to see if connected */
  464. int socket_is_connected( socket_t* const s )
  465. {
  466. #if defined(UNIT_TESTING)
  467. CHECK_RET( !fake_socket_connected, fake_socket_connected_ret );
  468. #endif
  469. CHECK_PTR_RET( s, FALSE );
  470. CHECK_RET( s->aiofd.rfd >= 0, FALSE );
  471. return s->connected;
  472. }
  473. socket_ret_t socket_connect( socket_t* const s,
  474. int8_t const * const hostname,
  475. uint16_t const port )
  476. {
  477. int len = 0;
  478. socket_ret_t ret = SOCKET_OK;
  479. struct sockaddr_in in_addr;
  480. struct sockaddr_un un_addr;
  481. CHECK_PTR_RET(s, SOCKET_BADPARAM);
  482. CHECK_RET((hostname != NULL) || (s->host != NULL), SOCKET_BADHOSTNAME);
  483. CHECK_RET( VALID_SOCKET_TYPE( s->type ), SOCKET_ERROR );
  484. CHECK_RET(((s->type != SOCKET_UNIX) && ((port > 0) || (s->port > 0))) || (s->type == SOCKET_UNIX), SOCKET_INVALIDPORT);
  485. CHECK_RET( !socket_is_connected( s ), SOCKET_CONNECTED );
  486. /* store port number if provided */
  487. if( port > 0 )
  488. s->port = port;
  489. /* look up and store the hostname if provided */
  490. if( hostname != NULL )
  491. {
  492. if ( (ret = socket_lookup_host(s, hostname)) != SOCKET_OK )
  493. return ret;
  494. }
  495. /* do the connect based on the type */
  496. switch(s->type)
  497. {
  498. case SOCKET_TCP:
  499. /* start the socket write event processing so we can catch connection */
  500. aiofd_enable_write_evt( &(s->aiofd), TRUE );
  501. /* try to make the TCP connection */
  502. CHECK_RET( socket_do_tcp_connect( s ), SOCKET_CONNECT_FAIL );
  503. break;
  504. case SOCKET_UNIX:
  505. /* start the socket write event processing so we can catch connection */
  506. aiofd_enable_write_evt( &(s->aiofd), TRUE );
  507. /* try to make the UNIX connection */
  508. CHECK_RET( socket_do_unix_connect( s ), SOCKET_CONNECT_FAIL );
  509. break;
  510. }
  511. return SOCKET_OK;
  512. }
  513. /* check to see if bound */
  514. int socket_is_bound( socket_t* const s )
  515. {
  516. #if defined(UNIT_TESTING)
  517. CHECK_RET( !fake_socket_bound, fake_socket_bound_ret );
  518. #endif
  519. CHECK_PTR_RET(s, FALSE);
  520. CHECK_RET( s->aiofd.rfd >= 0, FALSE );
  521. return s->bound;
  522. }
  523. socket_ret_t socket_bind( socket_t * const s,
  524. int8_t const * const host,
  525. uint16_t const port )
  526. {
  527. int len;
  528. int on = 1;
  529. socket_ret_t ret;
  530. struct sockaddr_in in_addr;
  531. struct sockaddr_un un_addr;
  532. CHECK_PTR_RET( s, SOCKET_BADPARAM );
  533. CHECK_RET( !socket_is_bound( s ), SOCKET_BOUND );
  534. CHECK_RET( VALID_SOCKET_TYPE( s->type ), SOCKET_ERROR );
  535. /* store port number if provided */
  536. if( port > 0 )
  537. s->port = port;
  538. /* look up and store the hostname if provided */
  539. if( host != NULL )
  540. {
  541. if ( (ret = socket_lookup_host(s, host)) != SOCKET_OK )
  542. return ret;
  543. }
  544. switch ( s->type )
  545. {
  546. case SOCKET_TCP:
  547. if ( SETSOCKOPT( s->aiofd.rfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
  548. {
  549. DEBUG( "failed to set the socket to reuse addr\n" );
  550. }
  551. /* try to bind the tcp socket */
  552. CHECK_RET( socket_do_tcp_bind( s ), SOCKET_ERROR );
  553. /* flag the socket as bound */
  554. s->bound = TRUE;
  555. break;
  556. case SOCKET_UNIX:
  557. /* try to bind the unix socket */
  558. CHECK_RET( socket_do_unix_bind( s ), SOCKET_ERROR );
  559. /* flag the socket as bound */
  560. s->bound = TRUE;
  561. break;
  562. }
  563. /* start the socket read even processing to catch incoming connections */
  564. CHECK_RET( aiofd_enable_read_evt( &(s->aiofd), TRUE ), SOCKET_ERROR );
  565. return SOCKET_OK;
  566. }
  567. socket_ret_t socket_listen( socket_t * const s, int const backlog )
  568. {
  569. CHECK_PTR_RET( s, SOCKET_BADPARAM );
  570. CHECK_RET( socket_is_bound( s ), SOCKET_BOUND );
  571. CHECK_RET( !socket_is_connected( s ), SOCKET_CONNECTED );
  572. /* now begin listening for incoming connections */
  573. if ( LISTEN( s->aiofd.rfd, backlog ) < 0 )
  574. {
  575. DEBUG( "failed to listen (errno: %d)\n", errno );
  576. return SOCKET_ERROR;
  577. }
  578. /* set the listen flag so that it doesn't error on 0 size read callbacks */
  579. /* TODO: check for errors and handle them properly */
  580. aiofd_set_listen( &(s->aiofd), TRUE );
  581. return SOCKET_OK;
  582. }
  583. int socket_is_listening( socket_t * const s )
  584. {
  585. CHECK_PTR_RET( s, FALSE );
  586. return aiofd_get_listen( &(s->aiofd) );
  587. }
  588. socket_t * socket_accept( socket_t * const s,
  589. socket_ops_t * const ops,
  590. evt_loop_t * const el,
  591. void * user_data )
  592. {
  593. int fd;
  594. int len;
  595. int32_t flags;
  596. socket_t * client;
  597. struct sockaddr_in in_addr;
  598. struct sockaddr_un un_addr;
  599. static aiofd_ops_t aiofd_ops =
  600. {
  601. &socket_aiofd_read_fn,
  602. &socket_aiofd_write_fn,
  603. &socket_aiofd_error_fn
  604. };
  605. CHECK_PTR_RET( s, NULL );
  606. CHECK_PTR_RET( ops, NULL );
  607. CHECK_PTR_RET( el, NULL );
  608. CHECK_RET( socket_is_bound( s ), NULL );
  609. CHECK_RET( VALID_SOCKET_TYPE( s->type ), NULL );
  610. client = CALLOC( 1, sizeof( socket_t ) );
  611. CHECK_PTR_RET_MSG( client, NULL, "failed to allocate new socket struct\n" );
  612. /* store the type */
  613. client->type = s->type;
  614. /* store the user_data pointer */
  615. client->user_data = user_data;
  616. /* copy the ops into place */
  617. MEMCPY( (void*)&(client->ops), ops, sizeof(socket_ops_t) );
  618. /* do the connect based on the type */
  619. switch(s->type)
  620. {
  621. case SOCKET_TCP:
  622. MEMSET( (void*)&in_addr, 0, sizeof( struct sockaddr_in ) );
  623. len = sizeof(in_addr);
  624. /* try to open a socket */
  625. if ( (fd = ACCEPT( s->aiofd.rfd, (struct sockaddr *)&in_addr, &len )) < 0 )
  626. {
  627. DEBUG("failed to accept incoming connection\n");
  628. socket_delete( (void*)client );
  629. return NULL;
  630. }
  631. else
  632. {
  633. DEBUG("accepted socket\n");
  634. }
  635. /* store the connection information */
  636. client->addr.s_addr = in_addr.sin_addr.s_addr;
  637. client->port = ntohs( in_addr.sin_port );
  638. /* turn off TCP naggle algorithm */
  639. flags = 1;
  640. if ( SETSOCKOPT( fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flags, sizeof(flags) ) < 0 )
  641. {
  642. DEBUG( "failed to turn on TCP no delay\n" );
  643. }
  644. else
  645. {
  646. DEBUG("turned on TCP no delay\n");
  647. }
  648. break;
  649. case SOCKET_UNIX:
  650. MEMSET( (void*)&un_addr, 0, sizeof( struct sockaddr_un ) );
  651. len = sizeof(un_addr);
  652. /* try to open a socket */
  653. if ( (fd = ACCEPT( s->aiofd.rfd, (struct sockaddr *)&un_addr, &len )) < 0 )
  654. {
  655. DEBUG("failed to open socket\n");
  656. socket_delete( (void*)client );
  657. return NULL;
  658. }
  659. else
  660. {
  661. DEBUG("accepted socket\n");
  662. }
  663. /* store the connection information */
  664. client->host = T(strdup((char const * const)un_addr.sun_path));
  665. break;
  666. }
  667. /* set the socket to non blocking mode */
  668. flags = FCNTL( fd, F_GETFL );
  669. if( FCNTL( fd, F_SETFL, (flags | O_NONBLOCK) ) < 0 )
  670. {
  671. DEBUG("failed to set socket to non-blocking\n");
  672. }
  673. else
  674. {
  675. DEBUG("socket is now non-blocking\n");
  676. }
  677. /* initialize the aiofd to manage the socket */
  678. if ( !aiofd_initialize( &(client->aiofd), fd, fd, &aiofd_ops, el, (void*)client ) )
  679. {
  680. DEBUG("failed to initialize the aiofd for the socket\n");
  681. socket_delete( (void*)client );
  682. return NULL;
  683. }
  684. else
  685. {
  686. DEBUG("aiofd initialized\n");
  687. }
  688. DEBUG( "socket connected\n" );
  689. client->connected = TRUE;
  690. if ( client->ops.connect_fn != NULL )
  691. {
  692. DEBUG( "calling socket connect callback\n" );
  693. /* call the connect callback */
  694. (*(client->ops.connect_fn))( client, client->user_data );
  695. }
  696. /* we're connected to start read event */
  697. if ( !aiofd_enable_read_evt( &(client->aiofd), TRUE ) )
  698. {
  699. DEBUG( "failed to enable read event\n" );
  700. socket_delete( (void*)client );
  701. return NULL;
  702. }
  703. return client;
  704. }
  705. socket_ret_t socket_disconnect( socket_t* const s )
  706. {
  707. CHECK_PTR_RET(s, SOCKET_BADPARAM);
  708. /* shutdown the aiofd */
  709. aiofd_deinitialize( &(s->aiofd) );
  710. if ( s->aiofd.rfd > 0 )
  711. {
  712. /* shutdown the socket */
  713. shutdown( s->aiofd.rfd, SHUT_RDWR );
  714. close( s->aiofd.rfd );
  715. s->aiofd.rfd = -1;
  716. s->aiofd.wfd = -1;
  717. }
  718. /* we're now disconnected */
  719. s->connected = FALSE;
  720. if ( s->ops.disconnect_fn != NULL )
  721. {
  722. /* call the disconnect callback */
  723. (*(s->ops.disconnect_fn))( s, s->user_data );
  724. }
  725. return SOCKET_OK;
  726. }
  727. socket_type_t socket_get_type( socket_t * const s )
  728. {
  729. CHECK_PTR_RET( s, SOCKET_UNKNOWN );
  730. return s->type;
  731. }
  732. int32_t socket_read( socket_t* const s,
  733. uint8_t * const buffer,
  734. int32_t const n )
  735. {
  736. CHECK_PTR_RET(s, 0);
  737. CHECK_PTR_RET(buffer, 0);
  738. CHECK_RET(n > 0, 0);
  739. return aiofd_read( &(s->aiofd), buffer, n );
  740. }
  741. socket_ret_t socket_write( socket_t * const s,
  742. uint8_t const * const buffer,
  743. size_t const n )
  744. {
  745. CHECK_PTR_RET( s, SOCKET_BADPARAM );
  746. return ( aiofd_write( &(s->aiofd), buffer, n ) ? SOCKET_OK : SOCKET_ERROR );
  747. }
  748. socket_ret_t socket_writev( socket_t * const s,
  749. struct iovec * iov,
  750. size_t iovcnt )
  751. {
  752. CHECK_PTR_RET( s, SOCKET_BADPARAM );
  753. return ( aiofd_writev( &(s->aiofd), iov, iovcnt ) ? SOCKET_OK : SOCKET_ERROR );
  754. }
  755. /* flush the socket output */
  756. socket_ret_t socket_flush( socket_t* const s )
  757. {
  758. CHECK_PTR_RET(s, SOCKET_BADPARAM);
  759. return aiofd_flush( &(s->aiofd) );
  760. }
  761. #if defined(UNIT_TESTING)
  762. #include <CUnit/Basic.h>
  763. socket_ret_t test_error_fn_ret = SOCKET_OK;
  764. socket_ret_t test_connect_fn_ret = SOCKET_OK;
  765. static socket_ret_t test_error_fn( socket_t * const s, int err, void * user_data )
  766. {
  767. *((int*)user_data) = TRUE;
  768. return test_error_fn_ret;
  769. }
  770. static socket_ret_t test_connect_fn( socket_t * const s, void * user_data )
  771. {
  772. *((int*)user_data) = TRUE;
  773. return test_connect_fn_ret;
  774. }
  775. void test_socket_private_functions( void )
  776. {
  777. int test_flag;
  778. int8_t * const host = T( strdup( "foo.com") );
  779. uint8_t buf[64];
  780. socket_t s, *p;
  781. socket_ops_t ops;
  782. reset_test_flags();
  783. MEMSET( &s, 0, sizeof(socket_t) );
  784. MEMSET( &ops, 0, sizeof(socket_ops_t) );
  785. /* test socket_get_errror */
  786. CU_ASSERT_FALSE( socket_get_error( NULL, NULL ) );
  787. CU_ASSERT_FALSE( socket_get_error( &s, NULL ) );
  788. fake_socket_getsockopt = TRUE;
  789. fake_socket_errval = TRUE;
  790. fake_socket_get_error_ret = TRUE;
  791. test_flag = FALSE;
  792. CU_ASSERT_TRUE( socket_get_error( &s, &test_flag ) );
  793. CU_ASSERT_TRUE( test_flag );
  794. reset_test_flags();
  795. /* test socket_do_tcp_connect */
  796. fake_connect = TRUE;
  797. fake_connect_ret = 0;
  798. CU_ASSERT_FALSE( socket_do_tcp_connect( NULL ) );
  799. s.type = SOCKET_UNIX;
  800. CU_ASSERT_FALSE( socket_do_tcp_connect( &s ) );
  801. s.type = SOCKET_TCP;
  802. CU_ASSERT_FALSE( socket_do_tcp_connect( &s ) );
  803. s.port = 1024;
  804. CU_ASSERT_TRUE( socket_do_tcp_connect( &s ) );
  805. fake_connect_ret = -1;
  806. CU_ASSERT_FALSE( socket_do_tcp_connect( &s ) );
  807. fake_errno = TRUE;
  808. fake_errno_value = EINPROGRESS;
  809. CU_ASSERT_TRUE( socket_do_tcp_connect( &s ) );
  810. fake_errno_value = EACCES;
  811. CU_ASSERT_FALSE( socket_do_tcp_connect( &s ) );
  812. reset_test_flags();
  813. /* test socket_do_unix_connect */
  814. fake_connect = TRUE;
  815. fake_connect_ret = 0;
  816. CU_ASSERT_FALSE( socket_do_unix_connect( NULL ) );
  817. s.type = SOCKET_TCP;
  818. CU_ASSERT_FALSE( socket_do_unix_connect( &s ) );
  819. s.type = SOCKET_UNIX;
  820. CU_ASSERT_FALSE( socket_do_unix_connect( &s ) );
  821. s.host = host;
  822. CU_ASSERT_TRUE( socket_do_unix_connect( &s ) );
  823. fake_connect_ret = -1;
  824. CU_ASSERT_FALSE( socket_do_unix_connect( &s ) );
  825. fake_errno = TRUE;
  826. fake_errno_value = EINPROGRESS;
  827. CU_ASSERT_TRUE( socket_do_unix_connect( &s ) );
  828. fake_errno_value = EACCES;
  829. CU_ASSERT_FALSE( socket_do_unix_connect( &s ) );
  830. reset_test_flags();
  831. /* test socket_lookup_host */
  832. MEMSET( &s, 0, sizeof( socket_t ) );
  833. CU_ASSERT_EQUAL( socket_lookup_host( NULL, NULL ), SOCKET_BADPARAM );
  834. CU_ASSERT_EQUAL( socket_lookup_host( &s, NULL ), SOCKET_BADHOSTNAME );
  835. CU_ASSERT_EQUAL( socket_lookup_host( &s, "foo.com" ), SOCKET_OK ); /* strdup's the hostname */
  836. FREE( s.host );
  837. s.type = SOCKET_UNIX;
  838. s.host = host;
  839. CU_ASSERT_EQUAL( socket_lookup_host( &s, NULL ), SOCKET_OK );
  840. reset_test_flags();
  841. /* test socket_aiofd_write_fn */
  842. CU_ASSERT_FALSE( socket_aiofd_write_fn( NULL, NULL, NULL ) );
  843. CU_ASSERT_FALSE( socket_aiofd_write_fn( &(s.aiofd), NULL, NULL ) );
  844. s.connected = TRUE;
  845. CU_ASSERT_TRUE( list_initialize( &(s.aiofd.wbuf), 2, NULL ) );
  846. CU_ASSERT_TRUE( list_push_tail( &(s.aiofd.wbuf), (void*)host ) );
  847. CU_ASSERT_TRUE( socket_aiofd_write_fn( &(s.aiofd), NULL, (void*)(&s) ) );
  848. CU_ASSERT_TRUE( socket_aiofd_write_fn( &(s.aiofd), (uint8_t const * const)&host, (void*)(&s) ) );
  849. s.connected = FALSE;
  850. s.aiofd.rfd = STDIN_FILENO;
  851. CU_ASSERT_FALSE( socket_aiofd_write_fn( &(s.aiofd), (uint8_t const * const)&host, (void*)(&s) ) );
  852. s.ops.error_fn = &test_error_fn;
  853. test_flag = FALSE;
  854. s.user_data = &test_flag;
  855. CU_ASSERT_FALSE( socket_aiofd_write_fn( &(s.aiofd), (uint8_t const * const)&host, (void*)(&s) ) );
  856. CU_ASSERT_TRUE( test_flag );
  857. fake_socket_getsockopt = TRUE;
  858. fake_socket_errval = 0;
  859. fake_socket_get_error_ret = TRUE;
  860. list_clear( &(s.aiofd.wbuf) );
  861. CU_ASSERT_FALSE( socket_aiofd_write_fn( &(s.aiofd), (uint8_t const * const)&host, (void*)(&s) ) );
  862. fake_socket_errval = -1;
  863. s.ops.error_fn = NULL;
  864. s.connected = FALSE;
  865. CU_ASSERT_FALSE( socket_aiofd_write_fn( &(s.aiofd), (uint8_t const * const)&host, (void*)(&s) ) );
  866. fake_socket_errval = 0;
  867. fake_socket_getsockopt = FALSE;
  868. reset_test_flags();
  869. /* test socket_aiofd_error_fn */
  870. CU_ASSERT_FALSE( socket_aiofd_error_fn( NULL, 0, NULL ) );
  871. CU_ASSERT_FALSE( socket_aiofd_error_fn( &(s.aiofd), 0, NULL ) );
  872. CU_ASSERT_TRUE( socket_aiofd_error_fn( &(s.aiofd), 0, (void*)(&s) ) );
  873. test_flag = FALSE;
  874. s.ops.error_fn = &test_error_fn;
  875. CU_ASSERT_TRUE( socket_aiofd_error_fn( &(s.aiofd), 0, (void*)(&s) ) );
  876. CU_ASSERT_TRUE( test_flag );
  877. reset_test_flags();
  878. /* test socket_aiofd_read_fn */
  879. CU_ASSERT_FALSE( socket_aiofd_read_fn( NULL, 0, NULL ) );
  880. CU_ASSERT_FALSE( socket_aiofd_read_fn( &(s.aiofd), 0, NULL ) );
  881. s.aiofd.rfd = 0;
  882. CU_ASSERT_FALSE( socket_aiofd_read_fn( &(s.aiofd), 0, (void*)(&s) ) );
  883. CU_ASSERT_TRUE( socket_aiofd_read_fn( &(s.aiofd), 1, (void*)(&s) ) );
  884. s.bound = TRUE;
  885. test_flag = FALSE;
  886. CU_ASSERT_TRUE( socket_aiofd_read_fn( &(s.aiofd), 0, (void*)(&s) ) );
  887. CU_ASSERT_FALSE( test_flag );
  888. s.ops.connect_fn = &test_connect_fn;
  889. test_connect_fn_ret = SOCKET_ERROR;
  890. test_flag = FALSE;
  891. CU_ASSERT_TRUE( socket_aiofd_read_fn( &(s.aiofd), 0, (void*)(&s) ) );
  892. CU_ASSERT_TRUE( test_flag );
  893. reset_test_flags();
  894. /* test socket_initialize */
  895. fake_socket = TRUE;
  896. fake_setsockopt = TRUE;
  897. fake_fcntl = TRUE;
  898. fake_aiofd_initialize = TRUE;
  899. MEMSET( &s, 0, sizeof( socket_t ) );
  900. MEMSET( &ops, 0, sizeof( socket_ops_t ) );
  901. CU_ASSERT_FALSE( socket_initialize( NULL, SOCKET_UNKNOWN, NULL, NULL, NULL ) );
  902. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_UNKNOWN, NULL, NULL, NULL ) );
  903. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_LAST, NULL, NULL, NULL ) );
  904. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, NULL, NULL, NULL ) );
  905. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, &ops, NULL, NULL ) );
  906. fake_socket_ret = -1;
  907. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, &ops, el, NULL ) );
  908. fake_socket_ret = 0;
  909. fake_setsockopt_ret = -1;
  910. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, &ops, el, NULL ) );
  911. fake_setsockopt_ret = 0;
  912. fake_fcntl_ret = -1;
  913. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, &ops, el, NULL ) );
  914. fake_fcntl_ret = 0;
  915. fake_aiofd_initialize_ret = FALSE;
  916. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_TCP, &ops, el, NULL ) );
  917. fake_aiofd_initialize_ret = TRUE;
  918. CU_ASSERT_TRUE( socket_initialize( &s, SOCKET_TCP, &ops, el, NULL ) );
  919. MEMSET( &s, 0, sizeof( socket_t ) );
  920. MEMSET( &ops, 0, sizeof( socket_ops_t ) );
  921. fake_socket_ret = -1;
  922. CU_ASSERT_FALSE( socket_initialize( &s, SOCKET_UNIX, &ops, el, NULL ) );
  923. fake_socket_ret = 0;
  924. CU_ASSERT_TRUE( socket_initialize( &s, SOCKET_UNIX, &ops, el, NULL ) );
  925. fake_socket = FALSE;
  926. fake_setsockopt = FALSE;
  927. fake_fcntl = FALSE;
  928. fake_aiofd_initialize = FALSE;
  929. reset_test_flags();
  930. /* test socket_is_connected */
  931. MEMSET( &s, 0, sizeof(socket_t) );
  932. CU_ASSERT_FALSE( socket_is_connected( NULL ) );
  933. s.aiofd.rfd = -1;
  934. CU_ASSERT_FALSE( socket_is_connected( &s ) );
  935. s.aiofd.rfd = STDIN_FILENO;
  936. CU_ASSERT_FALSE( socket_is_connected( &s ) );
  937. s.connected = TRUE;
  938. CU_ASSERT_TRUE( socket_is_connected( &s ) );
  939. reset_test_flags();
  940. /* test socket_is_bound */
  941. MEMSET( &s, 0, sizeof(socket_t) );
  942. CU_ASSERT_FALSE( socket_is_bound( NULL ) );
  943. s.aiofd.rfd = -1;
  944. CU_ASSERT_FALSE( socket_is_bound( &s ) );
  945. s.aiofd.rfd = STDIN_FILENO;
  946. CU_ASSERT_FALSE( socket_is_bound( &s ) );
  947. s.bound = TRUE;
  948. CU_ASSERT_TRUE( socket_is_bound( &s ) );
  949. reset_test_flags();
  950. /* test socket_connect */
  951. MEMSET( &s, 0, sizeof(socket_t) );
  952. CU_ASSERT_EQUAL( socket_connect( NULL, NULL, 0 ), SOCKET_BADPARAM );
  953. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_BADHOSTNAME );
  954. CU_ASSERT_EQUAL( socket_connect( &s, host, 0 ), SOCKET_INVALIDPORT );
  955. s.type = SOCKET_LAST;
  956. CU_ASSERT_EQUAL( socket_connect( &s, host, 0 ), SOCKET_ERROR );
  957. s.type = SOCKET_UNKNOWN;
  958. CU_ASSERT_EQUAL( socket_connect( &s, host, 0 ), SOCKET_ERROR );
  959. s.type = SOCKET_TCP;
  960. s.host = host;
  961. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_INVALIDPORT );
  962. fake_socket_connected = TRUE;
  963. fake_socket_connected_ret = TRUE;
  964. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 1024 ), SOCKET_CONNECTED );
  965. s.port = 1024;
  966. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_CONNECTED );
  967. s.type = SOCKET_UNIX;
  968. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_CONNECTED );
  969. s.type = SOCKET_TCP;
  970. fake_socket_connected_ret = FALSE;
  971. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_CONNECT_FAIL );
  972. fake_socket_connect = TRUE;
  973. fake_socket_connect_ret = TRUE;
  974. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_OK );
  975. fake_socket_connect_ret = FALSE;
  976. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_CONNECT_FAIL );
  977. s.type = SOCKET_UNIX;
  978. fake_socket_connect_ret = TRUE;
  979. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_OK );
  980. fake_socket_connect_ret = FALSE;
  981. CU_ASSERT_EQUAL( socket_connect( &s, NULL, 0 ), SOCKET_CONNECT_FAIL );
  982. reset_test_flags();
  983. /* test socket_bind */
  984. fake_setsockopt = TRUE;
  985. fake_aiofd_enable_read_evt = TRUE;
  986. fake_socket_bound = TRUE;
  987. fake_socket_lookup_host = TRUE;
  988. fake_socket_bind = TRUE;
  989. MEMSET( &s, 0, sizeof( socket_t ) );
  990. CU_ASSERT_EQUAL( socket_bind( NULL, NULL, 0 ), SOCKET_BADPARAM );
  991. fake_socket_bound_ret = TRUE;
  992. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_BOUND );
  993. fake_socket_bound_ret = FALSE;
  994. s.type = SOCKET_LAST;
  995. CU_ASSERT_EQUAL( socket_bind( &s, host, 0 ), SOCKET_ERROR );
  996. s.type = SOCKET_UNKNOWN;
  997. CU_ASSERT_EQUAL( socket_bind( &s, host, 0 ), SOCKET_ERROR );
  998. s.type = SOCKET_TCP;
  999. fake_socket_lookup_host_ret = SOCKET_ERROR;
  1000. CU_ASSERT_EQUAL( socket_bind( &s, host, 0 ), SOCKET_ERROR );
  1001. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1002. s.type = SOCKET_TCP;
  1003. fake_socket_bind_ret = FALSE;
  1004. fake_setsockopt_ret = 0;
  1005. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1006. fake_setsockopt_ret = 1;
  1007. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1008. fake_socket_bind_ret = TRUE;
  1009. fake_aiofd_enable_read_evt_ret = FALSE;
  1010. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1011. fake_aiofd_enable_read_evt_ret = TRUE;
  1012. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_OK );
  1013. s.type = SOCKET_UNIX;
  1014. fake_socket_bind_ret = FALSE;
  1015. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1016. fake_socket_bind_ret = TRUE;
  1017. fake_aiofd_enable_read_evt_ret = FALSE;
  1018. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_ERROR );
  1019. fake_aiofd_enable_read_evt_ret = TRUE;
  1020. CU_ASSERT_EQUAL( socket_bind( &s, NULL, 0 ), SOCKET_OK );
  1021. reset_test_flags();
  1022. /* test socket_do_tcp_bind */
  1023. MEMSET( &s, 0, sizeof(socket_t) );
  1024. CU_ASSERT_FALSE( socket_do_tcp_bind( NULL ) );
  1025. s.type = SOCKET_UNIX;
  1026. CU_ASSERT_FALSE( socket_do_tcp_bind( &s ) );
  1027. s.type = SOCKET_TCP;
  1028. CU_ASSERT_FALSE( socket_do_tcp_bind( &s ) );
  1029. s.port = 1024;
  1030. fake_bind = TRUE;
  1031. fake_bind_ret = 0;
  1032. CU_ASSERT_TRUE( socket_do_tcp_bind( &s ) );
  1033. fake_bind_ret = -1;
  1034. CU_ASSERT_FALSE( socket_do_tcp_bind( &s ) );
  1035. fake_bind = FALSE;
  1036. fake_bind_ret = 0;
  1037. reset_test_flags();
  1038. /* test socket_do_unix_bind */
  1039. MEMSET( &s, 0, sizeof(socket_t) );
  1040. CU_ASSERT_FALSE( socket_do_unix_bind( NULL ) );
  1041. s.type = SOCKET_TCP;
  1042. CU_ASSERT_FALSE( socket_do_unix_bind( &s ) );
  1043. s.type = SOCKET_UNIX;
  1044. CU_ASSERT_FALSE( socket_do_unix_bind( &s ) );
  1045. s.host = host;
  1046. fake_bind = TRUE;
  1047. fake_bind_ret = 0;
  1048. CU_ASSERT_TRUE( socket_do_unix_bind( &s ) );
  1049. fake_bind_ret = -1;
  1050. CU_ASSERT_FALSE( socket_do_unix_bind( &s ) );
  1051. fake_bind = FALSE;
  1052. fake_bind_ret = 0;
  1053. reset_test_flags();
  1054. /* test_socket_listen */
  1055. MEMSET( &s, 0, sizeof( socket_t ) );
  1056. CU_ASSERT_EQUAL( socket_listen( NULL, 0 ), SOCKET_BADPARAM );
  1057. fake_listen = TRUE;
  1058. fake_listen_ret = -1;
  1059. fake_socket_bound = TRUE;
  1060. fake_socket_bound_ret = FALSE;
  1061. CU_ASSERT_EQUAL( socket_listen( &s, 0 ), SOCKET_BOUND );
  1062. fake_socket_bound_ret = TRUE;
  1063. fake_socket_connected = TRUE;
  1064. fake_socket_connected_ret = TRUE;
  1065. CU_ASSERT_EQUAL( socket_listen( &s, 0 ), SOCKET_CONNECTED );
  1066. fake_socket_bound_ret = FALSE;
  1067. CU_ASSERT_EQUAL( socket_listen( &s, 0 ), SOCKET_BOUND );
  1068. fake_socket_bound_ret = TRUE;
  1069. fake_socket_connected_ret = FALSE;
  1070. fake_listen_ret = 0;
  1071. CU_ASSERT_EQUAL( socket_listen( &s, 0 ), SOCKET_OK );
  1072. fake_listen_ret = -1;
  1073. CU_ASSERT_EQUAL( socket_listen( &s, 0 ), SOCKET_ERROR );
  1074. reset_test_flags();
  1075. /* test socket_read */
  1076. fake_aiofd_read = TRUE;
  1077. MEMSET( &s, 0, sizeof(socket_t) );
  1078. CU_ASSERT_EQUAL( socket_read( NULL, NULL, 0 ), 0 );
  1079. CU_ASSERT_EQUAL( socket_read( &s, NULL, 0 ), 0 );
  1080. CU_ASSERT_EQUAL( socket_read( &s, buf, 0 ), 0 );
  1081. fake_aiofd_read_ret = 0;
  1082. CU_ASSERT_EQUAL( socket_read( &s, buf, 64 ), 0 );
  1083. fake_aiofd_read_ret = 64;
  1084. CU_ASSERT_EQUAL( socket_read( &s, buf, 64 ), 64 );
  1085. fake_aiofd_read = FALSE;
  1086. reset_test_flags();
  1087. /* test socket_write */
  1088. fake_aiofd_write = TRUE;
  1089. MEMSET( &s, 0, sizeof(socket_t) );
  1090. CU_ASSERT_EQUAL( socket_write( NULL, NULL, 0 ), SOCKET_BADPARAM );
  1091. fake_aiofd_write_ret = FALSE;
  1092. CU_ASSERT_EQUAL( socket_write( &s, NULL, 0 ), SOCKET_ERROR );
  1093. fake_aiofd_write_ret = TRUE;
  1094. CU_ASSERT_EQUAL( socket_write( &s, NULL, 0 ), SOCKET_OK );
  1095. fake_aiofd_write = FALSE;
  1096. reset_test_flags();
  1097. /* test socket_writev */
  1098. fake_aiofd_writev = TRUE;
  1099. MEMSET( &s, 0, sizeof(socket_t) );
  1100. CU_ASSERT_EQUAL( socket_writev( NULL, NULL, 0 ), SOCKET_BADPARAM );
  1101. fake_aiofd_writev_ret = FALSE;
  1102. CU_ASSERT_EQUAL( socket_writev( &s, NULL, 0 ), SOCKET_ERROR );
  1103. fake_aiofd_writev_ret = TRUE;
  1104. CU_ASSERT_EQUAL( socket_writev( &s, NULL, 0 ), SOCKET_OK );
  1105. fake_aiofd_writev = FALSE;
  1106. reset_test_flags();
  1107. /* test socket_accept */
  1108. fake_accept = TRUE;
  1109. fake_socket_bound = TRUE;
  1110. fake_setsockopt = TRUE;
  1111. fake_fcntl = TRUE;
  1112. fake_aiofd_initialize = TRUE;
  1113. fake_aiofd_enable_read_evt = TRUE;
  1114. MEMSET( &s, 0, sizeof(socket_t) );
  1115. MEMSET( &ops, 0, sizeof(socket_ops_t) );
  1116. CU_ASSERT_PTR_NULL( socket_accept( NULL, NULL, NULL, NULL ) );
  1117. CU_ASSERT_PTR_NULL( socket_accept( &s, NULL, NULL, NULL ) );
  1118. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, NULL, NULL ) );
  1119. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1120. fake_socket_bound_ret = FALSE;
  1121. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1122. fake_socket_bound_ret = TRUE;
  1123. s.type = SOCKET_LAST;
  1124. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1125. s.type = SOCKET_UNKNOWN;
  1126. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1127. s.type = SOCKET_TCP;
  1128. fail_alloc = TRUE;
  1129. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1130. fail_alloc = FALSE;
  1131. s.type = SOCKET_UNIX;
  1132. s.host = host;
  1133. fake_aiofd_initialize_ret = FALSE;
  1134. fake_fcntl_ret = -1;
  1135. fake_accept_ret = -1;
  1136. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1137. fake_accept_ret = 0;
  1138. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1139. s.type = SOCKET_TCP;
  1140. fake_accept_ret = -1;
  1141. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1142. fake_accept_ret = 0;
  1143. fake_setsockopt_ret = -1;
  1144. fake_fcntl_ret = -1;
  1145. fake_aiofd_initialize_ret = FALSE;
  1146. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1147. fake_fcntl_ret = 0;
  1148. fake_aiofd_initialize_ret = FALSE;
  1149. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1150. fake_setsockopt_ret = 0;
  1151. fake_fcntl_ret = -1;
  1152. fake_aiofd_initialize_ret = FALSE;
  1153. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1154. fake_fcntl_ret = 0;
  1155. fake_aiofd_initialize_ret = FALSE;
  1156. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1157. fake_aiofd_initialize_ret = TRUE;
  1158. fake_aiofd_enable_read_evt_ret = FALSE;
  1159. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, NULL ) );
  1160. test_flag = FALSE;
  1161. ops.connect_fn = &test_connect_fn;
  1162. CU_ASSERT_PTR_NULL( socket_accept( &s, &ops, el, &test_flag ) );
  1163. CU_ASSERT_TRUE( test_flag );
  1164. MEMSET( &ops, 0, sizeof(socket_ops_t) );
  1165. fake_aiofd_enable_read_evt_ret = TRUE;
  1166. p = socket_accept( &s, &ops, el, NULL );
  1167. CU_ASSERT_PTR_NOT_NULL( p );
  1168. FREE( p );
  1169. reset_test_flags();
  1170. FREE( host );
  1171. }
  1172. #endif