1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2015-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8
9%%	module
10
11#include "dk4conf.h"
12#include <libdk4sock/dk4sock.h>
13
14#if DK4_HAVE_LIMITS_H
15#ifndef LIMITS_H_INCLUDED
16#include <limits.h>
17#define	LIMITS_H_INCLUDED 1
18#endif
19#endif
20
21#if DK4_HAVE_STDINT_H
22#ifndef STDINT_H_INCLUDED
23#if defined(__cplusplus) && (!defined(__STDC_LIMIT_MACROS))
24#define __STDC_LIMIT_MACROS 1
25#endif
26#if defined(__cplusplus) && (!defined(__STDC_CONSTANT_MACROS))
27#define __STDC_CONSTANT_MACROS 1
28#endif
29#include <stdint.h>
30#define	STDINT_H_INCLUDED 1
31#endif
32#endif
33
34#if DK4_HAVE_STRING_H
35#ifndef	STRING_H_INCLUDED
36#include <string.h>
37#define	STRING_H_INCLUDED 1
38#endif
39#endif
40
41#include <libdk4base/dk4numco.h>
42
43#if DK4_HAVE_ASSERT_H
44#ifndef	ASSERT_H_INCLUDED
45#include <assert.h>
46#define	ASSERT_H_INCLUDED 1
47#endif
48#endif
49
50
51$!trace-include
52
53
54
55
56int
57dk4socket_send(
58  dk4_socket_t	 sock,
59  const void	*buf,
60  size_t	*pszbuf,
61  int		 flags,
62  long		 secs,
63  long		 usecs,
64  dk4_er_t	*erp
65)
66{
67  fd_set	 	wfds;
68  struct timeval	to;
69#if DK4_HAVE_SSIZE_T
70  ssize_t		bwr;
71#else
72  int			bwr;
73#endif
74  int			res;
75  int		 	back = DK4_SOCKET_RESULT_FAILED;
76
77#if	DK4_USE_ASSERT
78  assert(INVALID_SOCKET != sock);
79  assert(NULL != buf);
80  assert(NULL != pszbuf);
81  assert(0 < *pszbuf);
82#endif
83  if ((INVALID_SOCKET != sock) && (NULL != buf) && (NULL != pszbuf)) {
84    if (0 < *pszbuf) {
85#if DK4_HAVE_SSIZE_T
86      if ((dk4_um_t)(*pszbuf) <= (dk4_um_t)(SIZE_MAX / 2))
87#else
88      if ((dk4_um_t)(*pszbuf) <= (dk4_um_t)(INT_MAX))
89#endif
90      {
91        if ((0L != secs) || (0L != usecs)) {
92	  /*
93		  Timeout, check writability.
94	  */
95	  FD_ZERO(&wfds);
96	  FD_SET(sock, &wfds);
97	  to.tv_sec = secs;
98	  to.tv_usec = usecs;
99	  dk4socket_error_reset();
100	  res = select(((int)sock + 1), NULL, &wfds, NULL, &to);
101	  if (0 < res) {
102	    if (FD_ISSET(sock, &wfds)) {
103	      back = DK4_SOCKET_RESULT_SUCCESS;
104	    } else {
105	      /* Timeout */
106	      dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
107	    }
108	  } else {
109#if DK4_ON_WINDOWS
110	    if (SOCKET_ERROR == res)
111#else
112	    if (-1 == res)
113#endif
114	    {
115	      /* select error */
116	      dk4socket_error_report(erp, DK4_E_SOCKET_SELECT);
117	    }
118	    else
119	    {
120	      /* Timeout */
121	      dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
122	    }
123	  }
124        } else {
125          /*
126		  No timeout, can continue sending immediately.
127	  */
128          back = DK4_SOCKET_RESULT_SUCCESS;
129        }
130        if (DK4_SOCKET_RESULT_SUCCESS == back) {
131          back = DK4_SOCKET_RESULT_FAILED;
132	  /*
133		  Really send.
134	  */
135	  dk4socket_error_reset();
136#if DK4_ON_WINDOWS
137	  bwr = send(sock, buf, (int)(*pszbuf), flags);
138#else
139	  bwr = send(sock, buf, *pszbuf, flags);
140#endif
141	  if (0 <= bwr) {
142	    if ((size_t)bwr == *pszbuf) {
143	      back = DK4_SOCKET_RESULT_SUCCESS;
144	    } else {
145	      back = DK4_SOCKET_RESULT_IN_PROGRESS;
146	    }
147	    *pszbuf = (size_t)bwr;
148	  } else {
149	    dk4socket_error_report(erp, DK4_E_SOCKET_SEND);
150	    *pszbuf = 0;
151	  }
152        } else {
153	  *pszbuf = 0;
154	}
155      } else {
156        dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
157	*pszbuf = 0;
158      }
159    } else {
160      dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
161      *pszbuf = 0;
162    }
163  } else {
164    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
165    if (NULL != pszbuf) { *pszbuf = 0; }
166  }
167  return back;
168}
169
170
171
172int
173dk4socket_recv(
174  dk4_socket_t	 sock,
175  void		*buf,
176  size_t	*pszbuf,
177  int		 flags,
178  long		 secs,
179  long		 usecs,
180  dk4_er_t	*erp
181)
182{
183  fd_set		 rfds;
184  struct timeval	 to;
185#if DK4_HAVE_SSIZE_T
186  ssize_t		 bwr;
187#else
188  int			 bwr;
189#endif
190  int			 res;
191  int			 back = DK4_SOCKET_RESULT_FAILED;
192#if	DK4_USE_ASSERT
193  assert(INVALID_SOCKET != sock);
194  assert(NULL != buf);
195  assert(NULL != pszbuf);
196  assert(0 < *pszbuf);
197#endif
198  if ((INVALID_SOCKET != sock) && (NULL != buf) && (NULL != pszbuf)) {
199    if (0 < *pszbuf) {
200#if DK4_HAVE_SSIZE_T
201      if ((dk4_um_t)(*pszbuf) <= (dk4_um_t)(SIZE_MAX / 2))
202#else
203      if ((dk4_um_t)(*pszbuf) <= (dk4_um_t)(INT_MAX))
204#endif
205      {
206        if ((0L != secs) || (0L != usecs)) {
207	  /*
208		Timeout, check readability.
209	  */
210	  FD_ZERO(&rfds);
211	  FD_SET(sock, &rfds);
212	  to.tv_sec = secs;
213	  to.tv_usec = usecs;
214	  dk4socket_error_reset();
215	  res = select(((int)sock + 1), &rfds, NULL, NULL, &to);
216	  if (0 < res) {
217	    if (FD_ISSET(sock, &rfds)) {
218	      back = DK4_SOCKET_RESULT_SUCCESS;
219	    } else {
220	      dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
221	    }
222	  } else {
223#if DK4_ON_WINDOWS
224	    if (SOCKET_ERROR == res)
225#else
226	    if (-1 == res)
227#endif
228	    {
229	      dk4socket_error_report(erp, DK4_E_SOCKET_SELECT);
230	    }
231	    else
232	    {
233	      dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
234	    }
235	  }
236	} else {
237	  /*
238		No timeout.
239	  */
240	  back = DK4_SOCKET_RESULT_SUCCESS;
241	}
242	if (DK4_SOCKET_RESULT_SUCCESS == back) {
243	  back = DK4_SOCKET_RESULT_FAILED;
244	  dk4socket_error_reset();
245#if DK4_ON_WINDOWS
246	  bwr = recv(sock, buf, (int)(*pszbuf), flags);
247#else
248	  bwr = recv(sock, buf, *pszbuf, flags);
249#endif
250	  if (0 <= bwr) {
251	    back = DK4_SOCKET_RESULT_SUCCESS;
252	    *pszbuf = (size_t)bwr;
253	  } else {
254	    dk4socket_error_report(erp, DK4_E_SOCKET_RECV);
255	    *pszbuf = 0;
256	  }
257	}
258      }
259      else
260      {
261        dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
262      }
263    } else {
264      dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
265    }
266  } else {
267    dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
268  }
269  return back;
270}
271
272
273