1 /*
2 Copyright (C) 2015-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: dk4socka07.ctr
12 */
13 
14 /**	@file dk4socka07.c The dk4socka07 module.
15 */
16 
17 
18 
19 #include "dk4conf.h"
20 #include <libdk4sock/dk4sock.h>
21 #include <libdk4socka/dk4socka.h>
22 #include <libdk4base/dk4mem.h>
23 
24 #if DK4_HAVE_GETADDRINFO
25 #include <libdk4maio8d/dk4mao8d.h>
26 #else
27 #if DK4_CHAR_SIZE > 1
28 #include <libdk4maiowd/dk4maiwdus.h>
29 #include <libdk4c/dk4rec24.h>
30 #endif
31 #include <libdk4maio8d/dk4mai8dus.h>
32 #endif
33 
34 #include <libdk4maiodd/dk4maiddus.h>
35 #include <libdk4maiodd/dk4maodd.h>
36 #include <libdk4maiodh/dk4maodh.h>
37 
38 #if DK4_HAVE_ASSERT_H
39 #ifndef	ASSERT_H_INCLUDED
40 #include <assert.h>
41 #define	ASSERT_H_INCLUDED 1
42 #endif
43 #endif
44 
45 
46 
47 
48 
49 
50 /**	Constant texts used by module, not localized.
51 */
52 static const dkChar * const	dk4socket_03_kwnl[] = {
53 /* 0 */
54 dkT("\n\t"),
55 
56 /* 1 */
57 dkT(": "),
58 
59 /* 2 */
60 dkT("@"),
61 
62 NULL
63 
64 };
65 
66 
67 
68 /*
69 	Internal tool functions
70 	-----------------------
71 */
72 
73 /**	Report error from dk4socket_tcp_client_for_addr().
74 	@param	app		Application structure for logging.
75 	@param	afam		Address family.
76 	@param	sremote		Pointer to remote address buffer.
77 	@param	szremote	Remote address size.
78 	@param	slocal		Pointer to local address buffer.
79 	@param	szlocal		Local address size.
80 	@param	erp		Error report, required.
81 */
82 static
83 void
dk4socket_report_connection_error(dk4_app_t * app,int afam,const struct sockaddr * sremote,size_t szremote,const struct sockaddr * slocal,size_t szlocal,dk4_er_t * erp)84 dk4socket_report_connection_error(
85   dk4_app_t		*app,
86   int			 afam,
87   const struct sockaddr	*sremote,
88   size_t		 szremote,
89   const struct sockaddr	*slocal,
90   size_t		 szlocal,
91   dk4_er_t		*erp
92 )
93 {
94   const	dkChar *	 msgt[32];		/* Message components */
95   dkChar		 bdec[16*sizeof(dk4_um_t)];	/* Decimal */
96   dkChar		 bhex[16*sizeof(dk4_um_t)];	/* Hexadecimal */
97   dkChar		 bloc[128];		/* Local address */
98   dkChar		 brem[128];		/* Remote address */
99   const dkChar * const	*msga		= NULL;	/* Localized texts */
100   const dkChar		*fctname	= NULL;	/* Name of failed function */
101   const	dkChar		*msgtext	= NULL;	/* Text why fct failed */
102 #if VERSION_BEFORE_20150821
103   size_t		 szmsga		= 0;	/* Number of elems in msga */
104 #endif
105   size_t		 used		= 0;	/* No used elems in msgt */
106   int			 res		= 0;	/* Conversion result */
107   int			 bothbuf	= 0;	/* Flag: Have bdec and bhex */
108   int			 fctnmsg	= 0;	/* Flag: Use fct name */
109 
110   if (NULL != app) {
111     if (dk4app_log_do(app, DK4_LL_ERROR)) {
112 #if VERSION_BEFORE_20150821
113       szmsga = dk4socket_log_num_texts();
114 #endif
115       msga   = dk4socket_log_texts(app);
116       dk4socket_log_fctname_msg(&fctname, &msgtext, app, erp);
117       if (NULL == msgtext) {
118         res = dk4ma_write_decimal_signed(
119 	  bdec, DK4_SIZEOF(bdec,dkChar), (dk4_im_t)(erp->dt.iDetails1), 0, NULL
120 	);
121 	if (0 != res) {
122 	  res = dk4ma_write_hex_signed(
123 	    bhex,DK4_SIZEOF(bhex,dkChar),(dk4_im_t)(erp->dt.iDetails1),0,NULL
124 	  );
125 	  if (0 != res) { bothbuf = 1; }
126 	}
127       }
128       msgt[used++] = msga[41];
129       if ((NULL != slocal) && (0 < szlocal)) {
130         res = dk4socket_addr_port_to_text(
131 	  bloc, DK4_SIZEOF(bloc,dkChar), afam, slocal, szlocal, NULL
132 	);
133 	if (DK4_SOCKET_RESULT_SUCCESS == res) {
134 	  msgt[used++] = dk4socket_03_kwnl[0];
135 	  msgt[used++] = msga[42];
136 	  msgt[used++] = bloc;
137 	}
138       }
139       if ((NULL != sremote) && (0 < szremote)) {
140         res = dk4socket_addr_port_to_text(
141 	  brem, DK4_SIZEOF(brem,dkChar), afam, sremote, szremote, NULL
142 	);
143 	if (DK4_SOCKET_RESULT_SUCCESS == res) {
144 	  msgt[used++] = dk4socket_03_kwnl[0];
145 	  msgt[used++] = msga[43];
146 	  msgt[used++] = brem;
147 	}
148       }
149       switch (erp->ec) {
150         case DK4_E_INVALID_ARGUMENTS : {
151 	  msgt[used++] = dk4socket_03_kwnl[0];
152 	  msgt[used++] = msga[45];
153 	} break;
154 	case DK4_E_SOCKET_SOCKET : {
155 	  fctnmsg = 1;
156 	  msgt[used++] = dk4socket_03_kwnl[0];
157 	  msgt[used++] = msga[2];
158 	} break;
159 	case DK4_E_SOCKET_BIND : {
160 	  fctnmsg = 1;
161 	  msgt[used++] = dk4socket_03_kwnl[0];
162 	  msgt[used++] = msga[4];
163 	} break;
164 	case DK4_E_SOCKET_FCNTL : {
165 	  fctnmsg = 1;
166 	  msgt[used++] = dk4socket_03_kwnl[0];
167 	  msgt[used++] = msga[9];
168 	} break;
169 	case DK4_E_SOCKET_IOCTLSOCKET : {
170 	  fctnmsg = 1;
171 	  msgt[used++] = dk4socket_03_kwnl[0];
172 	  msgt[used++] = msga[9];
173 	} break;
174 	case DK4_E_SOCKET_CONNECT : {
175 	  fctnmsg = 1;
176 	  msgt[used++] = dk4socket_03_kwnl[0];
177 	  msgt[used++] = msga[7];
178 	} break;
179 	case DK4_E_SOCKET_TIMEOUT : {
180 	  msgt[used++] = dk4socket_03_kwnl[0];
181 	  msgt[used++] = msga[44];
182 	} break;
183 	case DK4_E_SOCKET_SELECT : {
184 	  fctnmsg = 1;
185 	  msgt[used++] = dk4socket_03_kwnl[0];
186 	  msgt[used++] = msga[44];
187 	} break;
188 	case DK4_E_SOCKET_GETSOCKOPT : {
189 	  fctnmsg = 1;
190 	  msgt[used++] = dk4socket_03_kwnl[0];
191 	  msgt[used++] = msga[8];
192 	} break;
193 	case DK4_E_SOCKET_SETSOCKOPT : {
194 	  fctnmsg = 1;
195 	  msgt[used++] = dk4socket_03_kwnl[0];
196 	  msgt[used++] = msga[8];
197 	} break;
198       }
199       if (0 != fctnmsg) {
200         if ((NULL != fctname) && ((NULL != msgtext) || (0 != bothbuf))) {
201 	  msgt[used++] = dk4socket_03_kwnl[0];
202 	  msgt[used++] = fctname;
203 	  msgt[used++] = dk4socket_03_kwnl[1];
204 	  if (NULL != msgtext) {
205 	    msgt[used++] = msgtext;
206 	  } else {
207 #if DK4_ON_WINDOWS
208 	    msgt[used++] = msga[40];
209 #else
210 	    msgt[used++] = msga[37];
211 #endif
212 	    msgt[used++] = bdec;
213 	    msgt[used++] = msga[38];
214 	    msgt[used++] = bhex;
215 	    msgt[used++] = msga[39];
216 	  }
217 	}
218       }
219       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
220     }
221   }
222 
223 }
224 
225 
226 
227 /**	Report error from dk4socket_tcp_client_for_addr().
228 	@param	app		Application structure for logging.
229 	@param	afam		Address family.
230 	@param	sremote		Pointer to remote address buffer.
231 	@param	szremote	Remote address size.
232 	@param	slocal		Pointer to local address buffer.
233 	@param	szlocal		Local address size.
234 	@param	erp		Error report, required.
235 */
236 static
237 void
dk4socket_report_connection_established(dk4_app_t * app,int afam,const struct sockaddr * sremote,size_t szremote,const struct sockaddr * slocal,size_t szlocal)238 dk4socket_report_connection_established(
239   dk4_app_t		*app,
240   int			 afam,
241   const struct sockaddr	*sremote,
242   size_t		 szremote,
243   const struct sockaddr	*slocal,
244   size_t		 szlocal
245 )
246 {
247   const	dkChar *	 msgt[32];		/* Message components */
248   dkChar		 bloc[128];		/* Local address */
249   dkChar		 brem[128];		/* Remote address */
250   const dkChar * const	*msga		= NULL;	/* Localized texts */
251 #if VERSION_BEFORE_20150821
252   size_t		 szmsga		= 0;	/* Number of elems in msga */
253 #endif
254   size_t		 used		= 0;	/* No used elems in msgt */
255   int			 res		= 0;	/* Conversion result */
256 
257   if (NULL != app) {
258     if (0 != dk4app_log_do(app, DK4_LL_PROGRESS)) {
259 #if VERSION_BEFORE_20150821
260       szmsga = dk4socket_log_num_texts();
261 #endif
262       msga   = dk4socket_log_texts(app);
263       msgt[used++] = msga[30];
264       if ((NULL != slocal) && (0 < szlocal)) {
265         res = dk4socket_addr_port_to_text(
266 	  bloc, DK4_SIZEOF(bloc,dkChar), afam, slocal, szlocal, NULL
267 	);
268 	if (DK4_SOCKET_RESULT_SUCCESS == res) {
269 	  msgt[used++] = dk4socket_03_kwnl[0];
270 	  msgt[used++] = msga[42];
271 	  msgt[used++] = bloc;
272 	}
273       }
274       if ((NULL != sremote) && (0 < szremote)) {
275         res = dk4socket_addr_port_to_text(
276 	  brem, DK4_SIZEOF(brem,dkChar), afam, sremote, szremote, NULL
277 	);
278 	if (DK4_SOCKET_RESULT_SUCCESS == res) {
279 	  msgt[used++] = dk4socket_03_kwnl[0];
280 	  msgt[used++] = msga[43];
281 	  msgt[used++] = brem;
282 	}
283       }
284       dk4app_log_msg(app, DK4_LL_PROGRESS, msgt, used);
285     }
286   }
287 }
288 
289 
290 
291 static
292 void
dk4socket_report_invalid_arguments(dk4_app_t * app)293 dk4socket_report_invalid_arguments(
294   dk4_app_t	*app
295 )
296 {
297   const dkChar *	 msgt[16];
298   const dkChar * const	*msga;
299 #if VERSION_BEFORE_20150821
300   size_t		 szmsga;
301 #endif
302   size_t		 used = 0;
303   if (NULL != app) {
304     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
305 #if VERSION_BEFORE_20150821
306       szmsga = dk4socket_log_num_texts();
307 #endif
308       msga   = dk4socket_log_texts(app);
309       msgt[used++] = msga[41];
310       msgt[used++] = dk4socket_03_kwnl[0];
311       msgt[used++] = msga[45];
312       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
313     }
314   }
315 }
316 
317 
318 #if DK4_HAVE_GETADDRINFO
319 /* +++++ +getaddrinfo +++++ */
320 
321 static
322 void
dk4socket_report_no_matching_addresses(const dkChar * hostname,dk4_app_t * app)323 dk4socket_report_no_matching_addresses(
324   const dkChar	*hostname,
325   dk4_app_t	*app
326 )
327 {
328   const dkChar		*msgt[16];
329   const dkChar * const	*msga;
330 #if VERSION_BEFORE_20150821
331   size_t		 szmsga;
332 #endif
333   if (NULL != app) {
334     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
335 #if VERSION_BEFORE_20150821
336       szmsga = dk4socket_log_num_texts();
337 #endif
338       msga   = dk4socket_log_texts(app);
339       msgt[0] = msga[41];
340       msgt[1] = dk4socket_03_kwnl[0];
341       msgt[2] = msga[43];
342       msgt[4] = hostname;
343       msgt[5] = dk4socket_03_kwnl[0];
344       msgt[6] = msga[46];
345       dk4app_log_msg(app, DK4_LL_ERROR, msgt, 7);
346     }
347   }
348 }
349 
350 
351 
352 static
353 void
dk4socket_report_gai(const dkChar * hostname,const dkChar * lsvcname,int res,int local,dk4_app_t * app,dk4_er_t * erp)354 dk4socket_report_gai(
355   const dkChar	*hostname,
356   const dkChar	*lsvcname,
357   int		 res,
358   int		 local,
359   dk4_app_t	*app,
360   dk4_er_t	*erp
361 )
362 {
363   dkChar		 bdec[16*sizeof(dk4_um_t)];
364   dkChar		 bhex[16*sizeof(dk4_um_t)];
365   const dkChar 		*msgt[16];
366   const dkChar * const	*msga;
367   const dkChar		*fctname	= NULL;
368   const dkChar		*msgtext	= NULL;
369 #if VERSION_BEFORE_20150821
370   size_t		 szmsga;
371 #endif
372   size_t		 used = 0;
373 
374   if (NULL != app) {
375     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
376 #if VERSION_BEFORE_20150821
377       szmsga = dk4socket_log_num_texts();
378 #endif
379       msga   = dk4socket_log_texts(app);
380       dk4socket_log_fctname_msg(&fctname, &msgtext, app, erp);
381       msgt[used++] = msga[41];
382       if ((NULL != hostname) && (0 == local)) {
383         msgt[used++] = dk4socket_03_kwnl[0];
384 	msgt[used++] = msga[20];
385 	msgt[used++] = dk4socket_03_kwnl[0];
386 	msgt[used++] = msga[21];
387 	msgt[used++] = hostname;
388 	if (NULL != lsvcname) {
389 	  msgt[used++] = dk4socket_03_kwnl[0];
390 	  msgt[used++] = msga[22];
391 	  msgt[used++] = lsvcname;
392 	}
393       } else {
394         msgt[used++] = dk4socket_03_kwnl[0];
395         msgt[used++] = msga[18];
396 	msgt[used++] = dk4socket_03_kwnl[0];
397 	msgt[used++] = msga[19];
398 	msgt[used++] = lsvcname;
399       }
400       if (NULL != fctname) {
401         if (NULL != msgtext) {
402 	  msgt[used++] = dk4socket_03_kwnl[0];
403 	  msgt[used++] = fctname;
404 	  msgt[used++] = dk4socket_03_kwnl[1];
405 	  msgt[used++] = msgtext;
406 	} else {
407 	  res = dk4ma_write_decimal_signed(
408 	    bdec,DK4_SIZEOF(bdec,dkChar),(dk4_im_t)(erp->dt.iDetails1),0,NULL
409 	  );
410 	  if (0 != res) {
411 	    res = dk4ma_write_hex_signed(
412 	      bhex,DK4_SIZEOF(bhex,dkChar),(dk4_im_t)(erp->dt.iDetails1),0,NULL
413 	    );
414 	    if (0 != res) {
415 	      msgt[used++] = dk4socket_03_kwnl[0];
416 	      msgt[used++] = fctname;
417 	      msgt[used++] = dk4socket_03_kwnl[1];
418 #if DK4_ON_WINDOWS
419 	      msgt[used++] = msga[40];
420 #else
421 	      msgt[used++] = msga[37];
422 #endif
423 	      msgt[used++] = bdec;
424 	      msgt[used++] = msga[38];
425 	      msgt[used++] = bhex;
426 	      msgt[used++] = msga[39];
427 	    }
428 	  }
429 	}
430       } else {
431       }
432       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
433     }
434   }
435 }
436 
437 #if DK4_CHAR_SIZE > 1
438 
439 /**	Create a socket using remote and optionally local address lists.
440 	@param	hostname	Remote host name.
441 	@param	rast	List of remote addresses.
442 	@param	last	List of local addresses, may be NULL.
443 	@param	secs	Seconds for timeout.
444 	@param	usecs	Microseconds for timeout.
445 	@param	app	Application structure for diagnostics, may be NULL.
446 	@return	Valid socket on success, INVALID_SOCKET on error.
447 */
448 static
449 dk4_socket_t
dk4socket_tcp_client_addresses_app(const dkChar * hostname,ADDRINFOW * rast,ADDRINFOW * last,long secs,long usecs,dk4_app_t * app)450 dk4socket_tcp_client_addresses_app(
451   const dkChar		*hostname,
452   ADDRINFOW		*rast,
453   ADDRINFOW		*last,
454   long			 secs,
455   long			 usecs,
456   dk4_app_t		*app
457 )
458 {
459   dk4_er_t		 er;
460   ADDRINFOW		*ra;
461   ADDRINFOW		*la;
462   dk4_socket_t		 back	= INVALID_SOCKET;
463   int			 mpf	= 0;
464 
465   ra = rast;
466   while ((INVALID_SOCKET == back) && (NULL != ra)) {
467     if (NULL != last) {
468       la = last;
469       while ((INVALID_SOCKET == back) && (NULL != la)) {
470         if (ra->ai_family == la->ai_family) {
471 	  mpf = 1;
472 	  dk4error_init(&er);
473 	  back = dk4socket_tcp_client_for_addr(
474 	    ra->ai_family,
475 	    ra->ai_addr, ra->ai_addrlen,
476 	    la->ai_addr, la->ai_addrlen,
477 	    secs, usecs, &er
478 	  );
479 	  if (INVALID_SOCKET != back) {
480 	    dk4socket_report_connection_established(
481 	      app, ra->ai_family,
482 	      ra->ai_addr, ra->ai_addrlen,
483 	      la->ai_addr, la->ai_addrlen
484 	    );
485 	    ra = NULL; la = NULL;
486 	  } else {
487 	    /* ERROR: Failed */
488 	    dk4socket_report_connection_error(
489 	      app, ra->ai_family,
490 	      ra->ai_addr, ra->ai_addrlen,
491 	      la->ai_addr, la->ai_addrlen,
492 	      &er
493 	    );
494 	  }
495 	}
496         if (NULL != la) { la = la->ai_next; }
497       }
498     } else {
499       mpf = 1;
500       dk4error_init(&er);
501       back = dk4socket_tcp_client_for_addr(
502         ra->ai_family, ra->ai_addr, ra->ai_addrlen, NULL, 0, secs, usecs, &er
503       );
504       if (INVALID_SOCKET != back) {
505 	dk4socket_report_connection_established(
506 	  app, ra->ai_family,
507 	  ra->ai_addr, ra->ai_addrlen,
508 	  NULL, 0
509 	);
510         ra = NULL;
511       } else {
512         /* ERROR: Failed */
513 	dk4socket_report_connection_error(
514 	  app,ra->ai_family,ra->ai_addr,ra->ai_addrlen,NULL,0,&er
515 	);
516       }
517     }
518     if (NULL != ra) { ra = ra->ai_next; }
519   }
520   if (INVALID_SOCKET == back) {
521     if (0 == mpf) {
522       /* ERROR: No matching address pair found (27) */
523       dk4socket_report_no_matching_addresses(hostname, app);
524     }
525   }
526 
527   return back;
528 }
529 
530 #else
531 
532 /**	Create a socket using remote and optionally local address lists.
533 	@param	hostname	Remote host name.
534 	@param	rast	List of remote addresses.
535 	@param	last	List of local addresses, may be NULL.
536 	@param	secs	Seconds for timeout.
537 	@param	usecs	Microseconds for timeout.
538 	@param	app	Application structure for diagnostics, may be NULL.
539 	@return	Valid socket on success, INVALID_SOCKET on error.
540 */
541 static
542 dk4_socket_t
dk4socket_tcp_client_addresses_app(const dkChar * hostname,struct addrinfo * rast,struct addrinfo * last,long secs,long usecs,dk4_app_t * app)543 dk4socket_tcp_client_addresses_app(
544   const dkChar		*hostname,
545   struct addrinfo	*rast,
546   struct addrinfo	*last,
547   long			 secs,
548   long			 usecs,
549   dk4_app_t		*app
550 )
551 {
552   dk4_er_t		 er;
553   struct addrinfo	*ra;
554   struct addrinfo	*la;
555   dk4_socket_t		 back	= INVALID_SOCKET;
556   int			 mpf	= 0;
557 
558   ra = rast;
559   while ((INVALID_SOCKET == back) && (NULL != ra)) {
560     if (NULL != last) {
561       la = last;
562       while ((INVALID_SOCKET == back) && (NULL != la)) {
563         if (ra->ai_family == la->ai_family) {
564 	  mpf = 1;
565 	  dk4error_init(&er);
566 	  back = dk4socket_tcp_client_for_addr(
567 	    ra->ai_family,
568 	    ra->ai_addr, ra->ai_addrlen,
569 	    la->ai_addr, la->ai_addrlen,
570 	    secs, usecs, &er
571 	  );
572 	  if (INVALID_SOCKET != back) {
573 	    dk4socket_report_connection_established(
574 	      app, ra->ai_family,
575 	      ra->ai_addr, ra->ai_addrlen,
576 	      la->ai_addr, la->ai_addrlen
577 	    );
578 	    ra = NULL; la = NULL;
579 	  } else {
580 	    /* ERROR: Failed */
581 	    dk4socket_report_connection_error(
582 	      app, ra->ai_family,
583 	      ra->ai_addr, ra->ai_addrlen,
584 	      la->ai_addr, la->ai_addrlen,
585 	      &er
586 	    );
587 	  }
588 	}
589         if (NULL != la) { la = la->ai_next; }
590       }
591     } else {
592       mpf = 1;
593       dk4error_init(&er);
594       back = dk4socket_tcp_client_for_addr(
595         ra->ai_family, ra->ai_addr, ra->ai_addrlen, NULL, 0, secs, usecs, &er
596       );
597       if (INVALID_SOCKET != back) {
598 	dk4socket_report_connection_established(
599 	  app, ra->ai_family,
600 	  ra->ai_addr, ra->ai_addrlen,
601 	  NULL, 0
602 	);
603         ra = NULL;
604       } else {
605         /* ERROR: Failed */
606 	dk4socket_report_connection_error(
607 	  app,ra->ai_family,ra->ai_addr,ra->ai_addrlen,NULL,0,&er
608 	);
609       }
610     }
611     if (NULL != ra) { ra = ra->ai_next; }
612   }
613   if (INVALID_SOCKET == back) {
614     if (0 == mpf) {
615       /* ERROR: No matching address pair found (27) */
616       dk4socket_report_no_matching_addresses(hostname, app);
617     }
618   }
619 
620   return back;
621 }
622 
623 #endif
624 
625 /* ----- +getaddrinfo ----- */
626 #else
627 /* +++++ -getaddrinfo +++++ */
628 
629 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
630 /**	used to initialize IPv6 address for binding local ports.
631 */
632 static const IN6_ADDR dk4socket_any6 = IN6ADDR_ANY_INIT;
633 #endif
634 
635 static
636 void
dk4socket_report_invalid_port_number(dk4_app_t * app,size_t i)637 dk4socket_report_invalid_port_number(dk4_app_t *app, size_t i)
638 {
639   const dkChar *	 msgt[16];
640   const dkChar * const	*msga;
641   size_t		 szmsga;
642   size_t		 used = 0;
643 
644   if (NULL != app) {
645     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
646       szmsga = dk4socket_log_num_texts();
647       msga   = dk4socket_log_texts(app);
648       msgt[used++] = msga[41];
649       msgt[used++] = dk4socket_03_kwnl[0];
650       msgt[used++] = msga[i];
651       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
652     }
653   }
654 }
655 
656 
657 static
658 void
dk4socket_report_service_not_found(dk4_app_t * app,const dkChar * svcname)659 dk4socket_report_service_not_found(dk4_app_t *app, const dkChar *svcname)
660 {
661   const dkChar *	 msgt[16];
662   const dkChar * const	*msga;
663   size_t		 szmsga;
664   size_t		 used = 0;
665 
666   if (NULL != app) {
667     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
668       szmsga = dk4socket_log_num_texts();
669       msga   = dk4socket_log_texts(app);
670       msgt[used++] = msga[23];
671       msgt[used++] = svcname;
672       msgt[used++] = msga[24];
673       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
674     }
675   }
676 }
677 
678 
679 
680 #if DK4_CHAR_SIZE > 1
681 
682 static
683 void
dk4socket_report_service_not_ascii(dk4_app_t * app,const dkChar * svcname)684 dk4socket_report_service_not_ascii(dk4_app_t *app, const dkChar *svcname)
685 {
686   const dkChar *	 msgt[16];
687   const dkChar * const	*msga;
688   size_t		 szmsga;
689   size_t		 used = 0;
690 
691   if (NULL != app) {
692     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
693       szmsga = dk4socket_log_num_texts();
694       msga   = dk4socket_log_texts(app);
695       msgt[used++] = msga[25];
696       msgt[used++] = svcname;
697       msgt[used++] = msga[26];
698       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
699     }
700   }
701 }
702 
703 #endif
704 
705 
706 
707 static
708 void
dk4socket_report_illegal_address_part(dk4_app_t * app,const dkChar * hostname,size_t i)709 dk4socket_report_illegal_address_part(
710   dk4_app_t	*app,
711   const dkChar	*hostname,
712   size_t	 i
713 )
714 {
715   const dkChar *	 msgt[16];
716   const dkChar * const	*msga;
717   size_t		 szmsga;
718   size_t		 used = 0;
719 
720   if (NULL != app) {
721     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
722       szmsga = dk4socket_log_num_texts();
723       msga   = dk4socket_log_texts(app);
724       msgt[used++] = msga[i];
725       if (NULL != hostname) {
726         msgt[used++] = dk4socket_03_kwnl[0];
727 	msgt[used++] = msga[43];
728 	msgt[used++] = hostname;
729       }
730       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
731     }
732   }
733 }
734 
735 
736 
737 static
738 void
dk4socket_report_host_name_problem(dk4_app_t * app,const dkChar * hostname,size_t i1,size_t i2)739 dk4socket_report_host_name_problem(
740   dk4_app_t	*app,
741   const dkChar	*hostname,
742   size_t	 i1,
743   size_t	 i2
744 )
745 {
746   const dkChar *	 msgt[16];
747   const dkChar * const	*msga;
748   size_t		 szmsga;
749   size_t		 used = 0;
750 
751   if (NULL != app) {
752     if (0 != dk4app_log_do(app, DK4_LL_ERROR)) {
753       szmsga = dk4socket_log_num_texts();
754       msga   = dk4socket_log_texts(app);
755       if (NULL != hostname) {
756 	msgt[used++] = msga[i1];
757 	msgt[used++] = hostname;
758 	msgt[used++] = msga[i2];
759       }
760       dk4app_log_msg(app, DK4_LL_ERROR, msgt, used);
761     }
762   }
763 }
764 
765 /* ----- -getaddrinfo ----- */
766 #endif
767 
768 
769 
770 /*
771 	Exported functions
772 	------------------
773 */
774 
775 #if DK4_CHAR_SIZE > 1
776 #if DK4_ON_WINDOWS
777 #if DK4_HAVE_GETADDRINFO
778 /* +++++ wchar_t (Windows), +getaddrinfo +++++ */
779 
780 
781 
782 dk4_socket_t
dk4socket_tcp_client_for_host_num_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,int nsrv,dk4_app_t * app)783 dk4socket_tcp_client_for_host_num_service_app(
784   const	dkChar		*hostname,
785   const	dkChar		*svcname,
786   const dkChar		*lsvcname,
787   long			 secs,
788   long			 usecs,
789   int			 nsrv,
790   dk4_app_t		*app
791 )
792 {
793   ADDRINFOW		 rhints;
794   ADDRINFOW		 lhints;
795   dk4_er_t		 er;
796   ADDRINFOW		*rast	= NULL;
797   ADDRINFOW		*last	= NULL;
798   dk4_socket_t		 back	= INVALID_SOCKET;
799   int			 res;
800 
801 #if	DK4_USE_ASSERT
802   assert(NULL != hostname);
803   assert(NULL != svcname);
804 #endif
805   if ((NULL != hostname) && (NULL != svcname)) {
806     DK4_MEMRES(&rhints, sizeof(rhints));
807     rhints.ai_family = AF_UNSPEC;
808     rhints.ai_socktype = SOCK_STREAM;
809     if (0 != nsrv) { rhints.ai_flags = AI_NUMERICSERV; }
810     rhints.ai_protocol = 0;
811     dk4error_init(&er);
812     res = GetAddrInfoW(hostname, svcname, &rhints, &rast);
813     if ((0 == res) && (NULL != rast)) {
814       if (NULL != lsvcname) {
815         DK4_MEMRES(&lhints, sizeof(lhints));
816 	lhints.ai_family = AF_UNSPEC;
817 	lhints.ai_socktype = SOCK_STREAM;
818 	lhints.ai_flags = AI_PASSIVE;
819 	if (0 != nsrv) { lhints.ai_flags |= AI_NUMERICSERV; }
820 	lhints.ai_protocol = 0;
821 	dk4error_init(&er);
822 	res = GetAddrInfoW(NULL, lsvcname, &lhints, &last);
823 	if ((0 == res) && (NULL != last)) {
824 	  back = dk4socket_tcp_client_addresses_app(
825 	    hostname, rast, last, secs, usecs, app
826 	  );
827 	  FreeAddrInfoW(last);
828 	} else {
829 	  /* ERROR: Failed to obtain local addresses to bind (18, 19) */
830 	  dk4error_set_idetails(&er, DK4_E_SOCKET_GETADDRINFO, res);
831 	  dk4socket_report_gai(NULL, lsvcname, res, 1, app, &er);
832 	}
833       } else {
834         back = dk4socket_tcp_client_addresses_app(
835 	  hostname, rast, NULL, secs, usecs, app
836 	);
837       }
838       FreeAddrInfoW(rast);
839     } else {
840       /* ERROR: Failed to obtain remote addresses (20, 21, 22) */
841       dk4error_set_idetails(&er, DK4_E_SOCKET_GETADDRINFO, res);
842       dk4socket_report_gai(hostname, svcname, res, 0, app, &er);
843     }
844   } else {
845     /* ERROR: Invalid arguments (bug) */
846     dk4socket_report_invalid_arguments(app);
847   }
848 
849   return back;
850 }
851 
852 
853 
854 dk4_socket_t
dk4socket_tcp_client_for_host_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,dk4_app_t * app)855 dk4socket_tcp_client_for_host_service_app(
856   const	dkChar		*hostname,
857   const	dkChar		*svcname,
858   const dkChar		*lsvcname,
859   long			 secs,
860   long			 usecs,
861   dk4_app_t		*app
862 )
863 {
864   return (
865     dk4socket_tcp_client_for_host_num_service_app(
866       hostname, svcname, lsvcname, secs, usecs, 0, app
867     )
868   );
869 }
870 
871 
872 
873 dk4_socket_t
dk4socket_tcp_client_for_host_port_app(const dkChar * hostname,unsigned short portno,unsigned short lportno,long secs,long usecs,dk4_app_t * app)874 dk4socket_tcp_client_for_host_port_app(
875   const dkChar		*hostname,
876   unsigned short	 portno,
877   unsigned short	 lportno,
878   long			 secs,
879   long			 usecs,
880   dk4_app_t		*app
881 )
882 {
883   dkChar		 rpnb[16*sizeof(dk4_um_t)];
884   dkChar		 lpnb[16*sizeof(dk4_um_t)];
885   dk4_er_t		 er;
886   dk4_socket_t		 back	= INVALID_SOCKET;
887   int			 res;
888 
889 #if	DK4_USE_ASSERT
890   assert(NULL != hostname);
891   assert(0 < portno);
892 #endif
893   if ((NULL != hostname) && (0 < portno)) {
894     dk4error_init(&er);
895     res = dk4ma_write_decimal_unsigned(
896       rpnb, DK4_SIZEOF(rpnb,dkChar), (dk4_um_t)portno, 0, &er
897     );
898     if (0 != res) {
899       if (0 < lportno) {
900         dk4error_init(&er);
901         res = dk4ma_write_decimal_unsigned(
902 	  lpnb, DK4_SIZEOF(lpnb,dkChar), (dk4_um_t)lportno, 0, &er
903 	);
904 	if (0 != res) {
905 	  back = dk4socket_tcp_client_for_host_num_service_app(
906 	    hostname, rpnb, lpnb, secs, usecs, 0, app
907 	  );
908 	} else {
909 	  /* ERROR: Failed to convert local port number to text, bug */
910 	}
911       } else {
912 	back = dk4socket_tcp_client_for_host_num_service_app(
913 	  hostname, rpnb, NULL, secs, usecs, 0, app
914 	);
915       }
916     } else {
917       /* ERROR: Failed to convert port number to text, bug */
918     }
919   } else {
920     /* ERROR: Invalid arguments (bug) */
921     dk4socket_report_invalid_arguments(app);
922   }
923 
924   return back;
925 }
926 
927 
928 
929 /* ----- wchar_t (Windows), +getaddrinfo ----- */
930 #else
931 /* +++++ wchar_t (Windows), -getaddrinfo +++++ */
932 
933 
934 
935 dk4_socket_t
dk4socket_tcp_client_for_host_num_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,int nsrv,dk4_app_t * app)936 dk4socket_tcp_client_for_host_num_service_app(
937   const	dkChar		*hostname,
938   const	dkChar		*svcname,
939   const dkChar		*lsvcname,
940   long			 secs,
941   long			 usecs,
942   int			 nsrv,
943   dk4_app_t		*app
944 )
945 {
946   char			 cppt[48];
947   char			 cplp[48];
948   dk4_er_t		 er;
949   struct servent	*serv	= NULL;
950   const dkChar		*endptr	= NULL;
951   dk4_socket_t		 back	= INVALID_SOCKET;
952   int			 res	= 0;
953   unsigned short	 rport	= 0U;
954   unsigned short	 lport	= 0U;
955   unsigned short	 iport	= 0U;
956 
957 #if	DK4_USE_ASSERT
958   assert(NULL != hostname);
959   assert(NULL != svcname);
960 #endif
961   if ((NULL != hostname) && (NULL != svcname)) {
962     dk4error_init(&er);
963     res = dk4ma_input_dk_dec_ushort(&rport, svcname, &endptr, 1, NULL);
964     if (0 == res) {
965       if (0 != dk4recode_wchar_t_to_char(cppt, sizeof(cppt), svcname, &er)) {
966         dk4socket_error_reset();
967 	serv = getservbyname(cppt, NULL);
968 	if (NULL != serv) {
969 	  iport = serv->s_port;
970 	  dk4socket_swap_bytes_if_not_bigendian((void *)(&iport),sizeof(iport));
971 	  rport = (unsigned short)iport;
972 	} else {
973 	  dk4socket_error_report(&er, DK4_E_SOCKET_GETSERVBYNAME);
974 	  /* ERROR: Service not found (23, 24) */
975 	  dk4socket_report_service_not_found(app, svcname);
976 	}
977       } else {
978         /* ERROR: Failed to convert service name (25, 26) */
979 	dk4socket_report_service_not_ascii(app, svcname);
980       }
981     }
982     if (0 < rport) {
983       if (NULL != lsvcname) {
984         endptr = NULL;
985 	dk4error_init(&er);
986 	res = dk4ma_input_dk_dec_ushort(&lport, lsvcname, &endptr, 1, NULL);
987 	if (0 == res) {
988 	  dk4error_init(&er);
989 	  if (0 != dk4recode_wchar_t_to_char(cplp,sizeof(cplp),lsvcname,&er)) {
990 	    dk4socket_error_reset();
991 	    serv = getservbyname(cplp, NULL);
992 	    if (NULL != serv) {
993 	      iport = serv->s_port;
994 	      dk4socket_swap_bytes_if_not_bigendian(
995 	        (void *)(&iport), sizeof(iport)
996 	      );
997 	      lport = (unsigned short)iport;
998 	    } else {
999 	      dk4socket_error_report(&er, DK4_E_SOCKET_GETSERVBYNAME);
1000 	      /* Service not found (23, 24) */
1001 	      dk4socket_report_service_not_found(app, lsvcname);
1002 	    }
1003 	  } else {
1004 	    /* ERROR: Text conversion failed (25, 26) */
1005 	    dk4socket_report_service_not_ascii(app, lsvcname);
1006 	  }
1007 	}
1008 	if (0 < lport) {
1009 	  back = dk4socket_tcp_client_for_host_port_app(
1010 	    hostname, rport, lport, secs, usecs, app
1011 	  );
1012 	} else {
1013 	  /* ERROR: Illegal local port number (28) */
1014 	  dk4socket_report_invalid_port_number(app, 28);
1015 	}
1016       } else {
1017         back = dk4socket_tcp_client_for_host_port_app(
1018 	  hostname, rport, 0, secs, usecs, app
1019 	);
1020       }
1021     } else {
1022       /* ERROR: Illegal remote port number (29) */
1023       dk4socket_report_invalid_port_number(app, 29);
1024     }
1025   } else {
1026     /* ERROR: Invalid arguments (bug) */
1027     dk4socket_report_invalid_arguments(app);
1028   }
1029 
1030   return back;
1031 }
1032 
1033 
1034 
1035 dk4_socket_t
dk4socket_tcp_client_for_host_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,dk4_app_t * app)1036 dk4socket_tcp_client_for_host_service_app(
1037   const	dkChar		*hostname,
1038   const	dkChar		*svcname,
1039   const dkChar		*lsvcname,
1040   long			 secs,
1041   long			 usecs,
1042   dk4_app_t		*app
1043 )
1044 {
1045   return (
1046     dk4socket_tcp_client_for_host_num_service_app(
1047       hostname, svcname, lsvcname, secs, usecs, 0, app
1048     )
1049   );
1050 }
1051 
1052 
1053 
1054 dk4_socket_t
dk4socket_tcp_client_for_host_port_app(const dkChar * hostname,unsigned short portno,unsigned short lportno,long secs,long usecs,dk4_app_t * app)1055 dk4socket_tcp_client_for_host_port_app(
1056   const dkChar		*hostname,
1057   unsigned short	 portno,
1058   unsigned short	 lportno,
1059   long			 secs,
1060   long			 usecs,
1061   dk4_app_t		*app
1062 )
1063 {
1064   char			  hona[1040];
1065 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
1066   struct sockaddr_in6	  sr6;
1067   struct sockaddr_in6	  sl6;
1068 #endif
1069   struct sockaddr_in	  sr4;
1070   struct sockaddr_in	  sl4;
1071   dk4_er_t		  er;
1072   char			**addrptr;
1073   struct hostent	 *hep;
1074   dk4_socket_t		  back	= INVALID_SOCKET;
1075 
1076 
1077 #if	DK4_USE_ASSERT
1078   assert(NULL != hostname);
1079   assert(0 < portno);
1080 #endif
1081   if ((NULL != hostname) && (0 < portno)) {
1082     dk4error_init(&er);
1083     if (0 != dk4recode_wchar_t_to_char(hona, sizeof(hona), hostname, &er)) {
1084       dk4socket_error_reset();
1085       hep = gethostbyname(hona);
1086       if (NULL != hep) {
1087         if (NULL != hep->h_addr_list) {
1088 	  switch (hep->h_addrtype) {
1089 	    case AF_INET : {
1090 	      if (4 == hep->h_length) {
1091 	        addrptr = hep->h_addr_list;
1092 		while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
1093 		  DK4_MEMRES(&sr4, sizeof(sr4));
1094 		  sr4.sin_family = AF_INET;
1095 		  sr4.sin_port   = dk4socket_htons(portno);
1096 		  DK4_MEMCPY(&(sr4.sin_addr), *addrptr, sizeof(IN_ADDR));
1097 		  dk4error_init(&er);
1098 		  if (0 != lportno) {
1099 		    DK4_MEMRES(&sl4, sizeof(sl4));
1100 		    sl4.sin_family = AF_INET;
1101 		    sl4.sin_port   = dk4socket_htons(lportno);
1102 		    sl4.sin_addr.s_addr = dk4socket_htonl(INADDR_ANY);
1103 		    back = dk4socket_tcp_client_for_addr(
1104 		      AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
1105 		      (struct sockaddr *)(&sl4), sizeof(sl4), secs, usecs, &er
1106 		    );
1107 		  } else {
1108 		    back = dk4socket_tcp_client_for_addr(
1109 		      AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
1110 		      NULL, 0, secs, usecs, &er
1111 		    );
1112 		  }
1113 		  if (INVALID_SOCKET == back) {
1114 		    /* ERROR: Failed */
1115 		    dk4socket_report_connection_error(
1116 		      app, AF_INET,
1117 		      (struct sockaddr *)(&sr4), sizeof(sr4),
1118 		      ((0 < lportno) ? ((struct sockaddr *)(&sl4)) : NULL),
1119 		      ((0 < lportno) ? (sizeof(sl4)) : 0),
1120 		      &er
1121 		    );
1122 		  } else {
1123 		    /* DEBUG: Connection established (30) */
1124 		    dk4socket_report_connection_established(
1125 		      app, AF_INET,
1126 		      (struct sockaddr *)(&sr4), sizeof(sr4),
1127 		      ((0 < lportno) ? ((struct sockaddr *)(&sl4)) : NULL),
1128 		      ((0 < lportno) ? (sizeof(sl4)) : 0)
1129 		    );
1130 		  }
1131 		  addrptr++;
1132 		}
1133 	      } else {
1134 	        /* ERROR: Illegal address length, bug (31) */
1135 		dk4socket_report_illegal_address_part(app, hostname, 31);
1136 	      }
1137 	    } break;
1138 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
1139 	    case AF_INET6 : {
1140 	      if (16 == hep->h_length) {
1141 	        addrptr = hep->h_addr_list;
1142 		while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
1143 		  DK4_MEMRES(&sr6, sizeof(sr6));
1144 		  sr6.sin6_family = AF_INET6;
1145 		  sr6.sin6_port   = dk4socket_htons(portno);
1146 		  DK4_MEMCPY(&(sr6.sin6_addr), *addrptr, sizeof(IN6_ADDR));
1147 		  dk4error_init(&er);
1148 		  if (0 < lportno) {
1149 		    DK4_MEMRES(&sl6, sizeof(sl6));
1150 		    sl6.sin6_family = AF_INET6;
1151 		    sl6.sin6_port   = dk4socket_htons(lportno);
1152 		    DK4_MEMCPY(&(sl6.sin6_addr),&dk4socket_any6,sizeof(IN6_ADDR));
1153 		    back = dk4socket_tcp_client_for_addr(
1154 		      AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
1155 		      (struct sockaddr *)(&sl6), sizeof(sl6), secs, usecs, &er
1156 		    );
1157 		  } else {
1158 		    back = dk4socket_tcp_client_for_addr(
1159 		      AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
1160 		      NULL, 0, secs, usecs, &er
1161 		    );
1162 		  }
1163 		  if (INVALID_SOCKET == back) {
1164 		    /* ERROR: Failed */
1165 		    dk4socket_report_connection_error(
1166 		      app, AF_INET6,
1167 		      (struct sockaddr *)(&sr6), sizeof(sr6),
1168 		      ((0 < lportno) ? ((struct sockaddr *)(&sl6)) : NULL),
1169 		      ((0 < lportno) ? (sizeof(sl6)) : 0),
1170 		      &er
1171 		    );
1172 		  } else {
1173 		    /* DEBUG: Connection established (30) */
1174 		    dk4socket_report_connection_established(
1175 		      app, AF_INET6,
1176 		      (struct sockaddr *)(&sr6), sizeof(sr6),
1177 		      ((0 < lportno) ? ((struct sockaddr *)(&sl6)) : NULL),
1178 		      ((0 < lportno) ? (sizeof(sl6)) : 0)
1179 		    );
1180 		  }
1181 		  addrptr++;
1182 		}
1183 	      } else {
1184 	        /* ERROR: Illegal address length, bug (31) */
1185 		dk4socket_report_illegal_address_part(app, hostname, 31);
1186 	      }
1187 	    } break;
1188 #endif
1189 	    default : {
1190 	      /* ERROR: Illegal address family (32) */
1191 	      dk4socket_report_illegal_address_part(app, hostname, 32);
1192 	    } break;
1193 	  }
1194 	} else {
1195 	  /* ERROR: Host not found (33, 34) */
1196 	  dk4socket_report_host_name_problem(app, hostname, 33, 34);
1197 	}
1198       } else {
1199         dk4socket_error_report(&er, DK4_E_SOCKET_GETHOSTBYNAME);
1200         /* ERROR: Host not found (33, 34) */
1201 	dk4socket_report_host_name_problem(app, hostname, 33, 34);
1202       }
1203     } else {
1204       /* ERROR: Failed to convert host name to ASCII (35, 36) */
1205       dk4socket_report_host_name_problem(app, hostname, 35, 36);
1206     }
1207   } else {
1208     /* ERROR: Invalid arguments (bug) */
1209     dk4socket_report_invalid_arguments(app);
1210   }
1211 
1212   return back;
1213 }
1214 
1215 
1216 
1217 /* ----- wchar_t (Windows), -getaddrinfo ----- */
1218 #endif
1219 #else
1220 #error	No support for networking with wchar_t strings!
1221 #endif
1222 #else
1223 #if DK4_HAVE_GETADDRINFO
1224 /* +++++ char, +getaddrinfo +++++ */
1225 
1226 dk4_socket_t
dk4socket_tcp_client_for_host_num_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,int nsrv,dk4_app_t * app)1227 dk4socket_tcp_client_for_host_num_service_app(
1228   const	dkChar		*hostname,
1229   const	dkChar		*svcname,
1230   const dkChar		*lsvcname,
1231   long			 secs,
1232   long			 usecs,
1233   int			 nsrv,
1234   dk4_app_t		*app
1235 )
1236 {
1237   struct addrinfo	 rhints;
1238   struct addrinfo	 lhints;
1239   dk4_er_t		 er;
1240   struct addrinfo	*raddrst = NULL;
1241   struct addrinfo	*laddrst = NULL;
1242   dk4_socket_t		 back	= INVALID_SOCKET;
1243   int			 res;
1244 
1245 #if	DK4_USE_ASSERT
1246   assert(NULL != hostname);
1247   assert(NULL != svcname);
1248 #endif
1249 
1250 
1251   if ((NULL != hostname) && (NULL != svcname)) {
1252     DK4_MEMRES(&rhints, sizeof(rhints));
1253     rhints.ai_family = AF_UNSPEC;
1254     rhints.ai_socktype = SOCK_STREAM;
1255     if (0 != nsrv) { rhints.ai_flags = AI_NUMERICSERV; }
1256     rhints.ai_protocol = 0;
1257     dk4error_init(&er);
1258     res = getaddrinfo(hostname, svcname, &rhints, &raddrst);
1259     if ((0 == res) && (NULL != raddrst)) {
1260       if (NULL != lsvcname) {
1261         DK4_MEMRES(&lhints, sizeof(lhints));
1262 	lhints.ai_family = AF_UNSPEC;
1263 	lhints.ai_socktype = SOCK_STREAM;
1264 	lhints.ai_flags = AI_PASSIVE;
1265 	if (0 != nsrv) { lhints.ai_flags |= AI_NUMERICSERV; }
1266 	lhints.ai_protocol = 0;
1267 	dk4error_init(&er);
1268 	res = getaddrinfo(NULL, lsvcname, &lhints, &laddrst);
1269 	if ((0 == res) && (NULL != laddrst)) {
1270 	  back = dk4socket_tcp_client_addresses_app(
1271 	    hostname, raddrst, laddrst, secs, usecs, app
1272 	  );
1273 	  freeaddrinfo(laddrst);
1274 	} else {
1275 	  /* ERROR: Failed to obtain local addresses (18, 19) */
1276 	  dk4error_set_idetails(&er, DK4_E_SOCKET_GETADDRINFO, res);
1277 	  dk4socket_report_gai(NULL, lsvcname, res, 1, app, &er);
1278 	}
1279       } else {
1280         back = dk4socket_tcp_client_addresses_app(
1281 	  hostname, raddrst, NULL, secs, usecs, app
1282 	);
1283       }
1284       freeaddrinfo(raddrst);
1285     } else {
1286       /* ERROR: Failed to obtain remote addresses (20, 21, 22) */
1287       dk4error_set_idetails(&er, DK4_E_SOCKET_GETADDRINFO, res);
1288       dk4socket_report_gai(hostname, svcname, res, 0, app, &er);
1289     }
1290   } else {
1291     /* ERROR: Invalid arguments (bug) */
1292     dk4socket_report_invalid_arguments(app);
1293   }
1294 
1295   return back;
1296 }
1297 
1298 
1299 
1300 dk4_socket_t
dk4socket_tcp_client_for_host_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,dk4_app_t * app)1301 dk4socket_tcp_client_for_host_service_app(
1302   const	dkChar		*hostname,
1303   const	dkChar		*svcname,
1304   const dkChar		*lsvcname,
1305   long			 secs,
1306   long			 usecs,
1307   dk4_app_t		*app
1308 )
1309 {
1310   return (
1311     dk4socket_tcp_client_for_host_num_service_app(
1312       hostname, svcname, lsvcname, secs, usecs, 0, app
1313     )
1314   );
1315 }
1316 
1317 
1318 
1319 dk4_socket_t
dk4socket_tcp_client_for_host_port_app(const dkChar * hostname,unsigned short portno,unsigned short lportno,long secs,long usecs,dk4_app_t * app)1320 dk4socket_tcp_client_for_host_port_app(
1321   const dkChar		*hostname,
1322   unsigned short	 portno,
1323   unsigned short	 lportno,
1324   long			 secs,
1325   long			 usecs,
1326   dk4_app_t		*app
1327 )
1328 {
1329   char			 rpn[16*sizeof(dk4_um_t)];
1330   char			 lpn[16*sizeof(dk4_um_t)];
1331   dk4_socket_t		 back	= INVALID_SOCKET;
1332   int			 res;
1333 
1334 #if	DK4_USE_ASSERT
1335   assert(NULL != hostname);
1336   assert(0 < portno);
1337 #endif
1338   if ((NULL != hostname) && (0 < portno)) {
1339     res = dk4ma_write_c8_decimal_unsigned(
1340       rpn, sizeof(rpn), (dk4_um_t)portno, 0, NULL
1341     );
1342     if (0 != res) {
1343       if (0 < lportno) {
1344         res = dk4ma_write_c8_decimal_unsigned(
1345 	  lpn, sizeof(lpn), (dk4_um_t)lportno, 0, NULL
1346 	);
1347 	if (0 != res) {
1348 	  back = dk4socket_tcp_client_for_host_num_service_app(
1349 	    hostname, rpn, lpn, secs, usecs, 1, app
1350 	  );
1351 	} else {
1352 	  /* ERROR: Failed to convert port number to text, bug */
1353 	}
1354       } else {
1355         back = dk4socket_tcp_client_for_host_num_service_app(
1356 	  hostname, rpn, NULL, secs, usecs, 1, app
1357 	);
1358       }
1359     } else {
1360       /* ERROR: Failed to convert port number to text, bug */
1361     }
1362   } else {
1363     /* ERROR: Invalid arguments (bug) */
1364     dk4socket_report_invalid_arguments(app);
1365   }
1366 
1367   return back;
1368 }
1369 
1370 
1371 
1372 /* ----- char, +getaddrinfo ----- */
1373 #else
1374 /* +++++ char, -getaddrinfo ----- */
1375 
1376 
1377 
1378 dk4_socket_t
dk4socket_tcp_client_for_host_num_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,int nsrv,dk4_app_t * app)1379 dk4socket_tcp_client_for_host_num_service_app(
1380   const	dkChar		*hostname,
1381   const	dkChar		*svcname,
1382   const dkChar		*lsvcname,
1383   long			 secs,
1384   long			 usecs,
1385   int			 nsrv,
1386   dk4_app_t		*app
1387 )
1388 {
1389   const char		*endptr	= NULL;
1390   struct servent	*serv	= NULL;
1391   dk4_socket_t		 back	= INVALID_SOCKET;
1392   int			 res	= 0;
1393   int			 iport	= 0;
1394   unsigned short	 rport	= 0;
1395   unsigned short	 lport	= 0;
1396 
1397 #if	DK4_USE_ASSERT
1398   assert(NULL != hostname);
1399   assert(NULL != svcname);
1400 #endif
1401   if ((NULL != hostname) && (NULL != svcname)) {
1402     res = dk4ma_input_c8_dec_ushort(&rport, svcname, &endptr, 1, NULL);
1403     if (0 == res) {
1404       dk4socket_error_reset();
1405       serv = getservbyname(svcname, NULL);
1406       if (NULL != serv) {
1407         iport = serv->s_port;
1408 	dk4socket_swap_bytes_if_not_bigendian((void *)(&iport), sizeof(iport));
1409 	rport = (unsigned short)iport;
1410       } else {
1411         /* ERROR: Service name for remote port not found (23, 24) */
1412 	dk4socket_report_service_not_found(app, svcname);
1413       }
1414     }
1415     if (0 != rport) {
1416       if (NULL != lsvcname) {
1417         endptr = NULL;
1418 	res = dk4ma_input_c8_dec_ushort(&lport, lsvcname, &endptr, 1, NULL);
1419 	if (0 == res) {
1420 	  dk4socket_error_reset();
1421 	  serv = getservbyname(lsvcname, NULL);
1422 	  if (NULL != serv) {
1423 	    iport = serv->s_port;
1424 	    dk4socket_swap_bytes_if_not_bigendian(
1425 	      (void *)(&iport), sizeof(iport)
1426 	    );
1427 	    lport = (unsigned short)iport;
1428 	  } else {
1429 	    /* ERROR: Service name for local port not found (23, 24) */
1430 	    dk4socket_report_service_not_found(app, lsvcname);
1431 	  }
1432 	}
1433 	if (0 != lport) {
1434 	  back = dk4socket_tcp_client_for_host_port_app(
1435 	    hostname, rport, lport, secs, usecs, app
1436 	  );
1437 	} else {
1438 	  /* ERROR: Illegal local port number (28) */
1439 	  dk4socket_report_invalid_port_number(app, 28);
1440 	}
1441       } else {
1442         back = dk4socket_tcp_client_for_host_port_app(
1443 	  hostname, rport, 0, secs, usecs, app
1444 	);
1445       }
1446     } else {
1447       /* ERROR: Illegal remote port number (29) */
1448       dk4socket_report_invalid_port_number(app, 29);
1449     }
1450   } else {
1451     /* ERROR: Invalid arguments (bug) */
1452     dk4socket_report_invalid_arguments(app);
1453   }
1454 
1455   return back;
1456 }
1457 
1458 
1459 
1460 dk4_socket_t
dk4socket_tcp_client_for_host_service_app(const dkChar * hostname,const dkChar * svcname,const dkChar * lsvcname,long secs,long usecs,dk4_app_t * app)1461 dk4socket_tcp_client_for_host_service_app(
1462   const	dkChar		*hostname,
1463   const	dkChar		*svcname,
1464   const dkChar		*lsvcname,
1465   long			 secs,
1466   long			 usecs,
1467   dk4_app_t		*app
1468 )
1469 {
1470   return (
1471     dk4socket_tcp_client_for_host_num_service_app(
1472       hostname, svcname, lsvcname, secs, usecs, 0, app
1473     )
1474   );
1475 }
1476 
1477 
1478 
1479 dk4_socket_t
dk4socket_tcp_client_for_host_port_app(const dkChar * hostname,unsigned short portno,unsigned short lportno,long secs,long usecs,dk4_app_t * app)1480 dk4socket_tcp_client_for_host_port_app(
1481   const dkChar		*hostname,
1482   unsigned short	 portno,
1483   unsigned short	 lportno,
1484   long			 secs,
1485   long			 usecs,
1486   dk4_app_t		*app
1487 )
1488 {
1489   dk4_er_t		  er;
1490 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
1491   struct sockaddr_in6	  sr6;
1492   struct sockaddr_in6	  sl6;
1493 #endif
1494   struct sockaddr_in	  sr4;
1495   struct sockaddr_in	  sl4;
1496   char			**addrptr;
1497   struct hostent	 *hep		= NULL;
1498   dk4_socket_t		  back		= INVALID_SOCKET;
1499 
1500 #if	DK4_USE_ASSERT
1501   assert(NULL != hostname);
1502   assert(0 < portno);
1503 #endif
1504   if ((NULL != hostname) && (0 < portno)) {
1505     dk4error_init(&er);
1506     dk4socket_error_reset();
1507     hep = gethostbyname(hostname);
1508     if (NULL != hep) {
1509       if (NULL != hep->h_addr_list) {
1510         switch (hep->h_addrtype) {
1511 	  case AF_INET : {
1512 	    if (4 == hep->h_length) {
1513 	      addrptr = hep->h_addr_list;
1514 	      while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
1515 	        DK4_MEMRES(&sr4, sizeof(sr4));
1516 		sr4.sin_family = AF_INET;
1517 		sr4.sin_port   = dk4socket_htons(portno);
1518 		DK4_MEMCPY(&(sr4.sin_addr), *addrptr, sizeof(IN_ADDR));
1519 		dk4error_init(&er);
1520 		if (0 != lportno) {
1521 		  DK4_MEMRES(&sl4, sizeof(sl4));
1522 		  sl4.sin_family = AF_INET;
1523 		  sl4.sin_port   = dk4socket_htons(lportno);
1524 		  sl4.sin_addr.s_addr = dk4socket_htonl(INADDR_ANY);
1525 		  back = dk4socket_tcp_client_for_addr(
1526 		    AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
1527 		    (struct sockaddr *)(&sl4), sizeof(sl4), secs, usecs, &er
1528 		  );
1529 		} else {
1530 		  back = dk4socket_tcp_client_for_addr(
1531 		    AF_INET, (struct sockaddr *)(&sr4), sizeof(sr4),
1532 		    NULL, 0, secs, usecs, &er
1533 		  );
1534 		}
1535 		if (INVALID_SOCKET == back) {
1536 		  /* ERROR: Failed */
1537 		  dk4socket_report_connection_error(
1538 		    app, AF_INET,
1539 		    (struct sockaddr *)(&sr4), sizeof(sr4),
1540 		    ((0 < lportno) ? ((struct sockaddr *)(&sl4)) : NULL),
1541 		    ((0 < lportno) ? (sizeof(sl4)) : 0),
1542 		    &er
1543 		  );
1544 		} else {
1545 		  /* DEBUG: Connection established (30) */
1546 		  dk4socket_report_connection_established(
1547 		    app, AF_INET,
1548 		    (struct sockaddr *)(&sr4), sizeof(sr4),
1549 		    ((0 < lportno) ? ((struct sockaddr *)(&sl4)) : NULL),
1550 		    ((0 < lportno) ? (sizeof(sl4)) : 0)
1551 		  );
1552 		}
1553 	        addrptr++;
1554 	      }
1555 	    } else {
1556 	      /* ERROR: Illegal address length (31) */
1557 	      dk4socket_report_illegal_address_part(app, hostname, 31);
1558 	    }
1559 	  } break;
1560 #if DK4_HAVE_STRUCT_SOCKADDR_IN6
1561 	  case AF_INET6 : {
1562 	    if (16 == hep->h_length) {
1563 	      addrptr = hep->h_addr_list;
1564 	      while ((INVALID_SOCKET == back) && (NULL != *addrptr)) {
1565 	        DK4_MEMRES(&sr6, sizeof(sr6));
1566 		sr6.sin6_family = AF_INET6;
1567 		sr6.sin6_port   = dk4socket_htons(portno);
1568 		DK4_MEMCPY(&(sr6.sin6_addr), *addrptr, sizeof(IN6_ADDR));
1569 		dk4error_init(&er);
1570 		if (0 != lportno) {
1571 		  DK4_MEMRES(&sl6, sizeof(sl6));
1572 		  sl6.sin6_family = AF_INET6;
1573 		  sl6.sin6_port   = dk4socket_htons(lportno);
1574 		  DK4_MEMCPY(&(sl6.sin6_addr),&dk4socket_any6,sizeof(IN6_ADDR));
1575 		  back = dk4socket_tcp_client_for_addr(
1576 		    AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
1577 		    (struct sockaddr *)(&sl6), sizeof(sl6),
1578 		    secs, usecs, &er
1579 		  );
1580 		} else {
1581 		  back = dk4socket_tcp_client_for_addr(
1582 		    AF_INET6, (struct sockaddr *)(&sr6), sizeof(sr6),
1583 		    NULL, 0, secs, usecs, &er
1584 		  );
1585 		}
1586 		if (INVALID_SOCKET == back) {
1587 		  /* ERROR: Failed */
1588 		  dk4socket_report_connection_error(
1589 		    app, AF_INET6,
1590 		    (struct sockaddr *)(&sr6), sizeof(sr6),
1591 		    ((0 < lportno) ? ((struct sockaddr *)(&sl6)) : NULL),
1592 		    ((0 < lportno) ? (sizeof(sl6)) : 0),
1593 		    &er
1594 		  );
1595 		} else {
1596 		  /* DEBUG: Connection established (30) */
1597 		  dk4socket_report_connection_established(
1598 		    app, AF_INET6,
1599 		    (struct sockaddr *)(&sr6), sizeof(sr6),
1600 		    ((0 < lportno) ? ((struct sockaddr *)(&sl6)) : NULL),
1601 		    ((0 < lportno) ? (sizeof(sl6)) : 0)
1602 		  );
1603 		}
1604 	        addrptr++;
1605 	      }
1606 	    } else {
1607 	      /* ERROR: Illegal address length (31) */
1608 	      dk4socket_report_illegal_address_part(app, hostname, 31);
1609 	    }
1610 	  } break;
1611 #endif
1612 	  default : {
1613 	    /* ERROR: Illegal address family (32) */
1614 	    dk4socket_report_illegal_address_part(app, hostname, 32);
1615 	  } break;
1616 	}
1617       } else {
1618         /* ERROR: Remote host address not found! (33, 34) */
1619 	dk4socket_report_host_name_problem(app, hostname, 33, 34);
1620       }
1621     } else {
1622       dk4socket_error_report(&er, DK4_E_SOCKET_GETHOSTBYNAME);
1623       /* ERROR: Remote host address not found! (33, 34) */
1624       dk4socket_report_host_name_problem(app, hostname, 33, 34);
1625     }
1626   } else {
1627     /* ERROR: Invalid arguments (bug) */
1628     dk4socket_report_invalid_arguments(app);
1629   }
1630 
1631   return back;
1632 }
1633 
1634 
1635 
1636 /* ----- char, -getaddrinfo ----- */
1637 #endif
1638 #endif
1639 
1640