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