2438 |
2430 |
2439 |domainClass addr addrLen nReceived error| |
2431 |domainClass addr addrLen nReceived error| |
2440 |
2432 |
2441 domainClass := self class socketAddressClassForDomain:domain. |
2433 domainClass := self class socketAddressClassForDomain:domain. |
2442 domainClass isNil ifTrue:[ |
2434 domainClass isNil ifTrue:[ |
2443 ^ self error:'invalid (unsupported) domain'. |
2435 ^ self error:'invalid (unsupported) domain'. |
2444 ]. |
2436 ]. |
2445 (anAddressBuffer isKindOf:SocketAddress) ifTrue:[ |
2437 anAddressBuffer isSocketAddress ifTrue:[ |
2446 anAddressBuffer class == domainClass ifFalse:[ |
2438 anAddressBuffer class == domainClass ifFalse:[ |
2447 ^ self error:'addressBuffer class mismatch (domain)'. |
2439 ^ self error:'addressBuffer class mismatch (domain)'. |
2448 ]. |
2440 ]. |
2449 addr := anAddressBuffer. |
2441 addr := anAddressBuffer. |
2450 ] ifFalse:[ |
2442 ] ifFalse:[ |
2451 anAddressBuffer notNil ifTrue:[ |
2443 anAddressBuffer notNil ifTrue:[ |
2452 addr := domainClass new. |
2444 addr := domainClass new. |
2453 ]. |
2445 ]. |
2454 ]. |
2446 ]. |
2455 |
2447 |
2456 %{ |
2448 %{ |
2457 #ifndef NO_SOCKET |
2449 #ifndef NO_SOCKET |
2458 OBJ fp = __INST(handle); |
2450 OBJ fp = __INST(handle); |
2459 |
2451 |
2460 if (fp != nil) { |
2452 if (fp != nil) { |
2461 SOCKET sock; |
2453 SOCKET sock; |
2462 size_t objSize; |
2454 size_t objSize; |
2463 union sockaddr_u sa; |
2455 union sockaddr_u sa; |
2464 socklen_t alen = 0; |
2456 socklen_t alen = 0; |
2465 INT n, offs; |
2457 INT n, offs; |
2466 int _flags = __longIntVal(flags); |
2458 int _flags = __longIntVal(flags); |
2467 char *extPtr; |
2459 char *extPtr; |
2468 unsigned char *allocatedBuffer = NULL, *buffer = NULL; |
2460 unsigned char *allocatedBuffer = NULL, *buffer = NULL; |
2469 |
2461 |
2470 sock = SOCKET_FROM_FILE_OBJECT(fp); |
2462 sock = SOCKET_FROM_FILE_OBJECT(fp); |
2471 |
2463 |
2472 if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; |
2464 if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; |
2473 if (__isSmallInteger(nBytes)) { |
2465 if (__isSmallInteger(nBytes)) { |
2474 if (__intVal(nBytes) < objSize) { |
2466 if (__intVal(nBytes) < objSize) { |
2475 objSize = __intVal(nBytes); |
2467 objSize = __intVal(nBytes); |
2476 } |
2468 } |
2477 } |
2469 } |
2478 # ifdef DO_WRAP_CALLS |
2470 # ifdef DO_WRAP_CALLS |
2479 if (extPtr) { |
2471 if (extPtr) { |
2480 buffer = extPtr + offs; |
2472 buffer = extPtr + offs; |
2481 } else { |
2473 } else { |
2482 allocatedBuffer = buffer = (char *)malloc(objSize); |
2474 allocatedBuffer = buffer = (char *)malloc(objSize); |
2483 } |
2475 } |
2484 |
2476 |
2485 do { |
2477 do { |
2486 __threadErrno = 0; |
2478 __threadErrno = 0; |
2487 alen = sizeof(sa); |
2479 alen = sizeof(sa); |
2488 n = (INT)STX_WSA_NOINT_CALL6("recvfrom", recvfrom, sock, buffer, objSize, _flags, (struct sockaddr *)&sa, &alen); |
2480 n = (INT)STX_WSA_NOINT_CALL6("recvfrom", recvfrom, sock, buffer, objSize, _flags, (struct sockaddr *)&sa, &alen); |
2489 } while ((n < 0) && (__threadErrno == EINTR)); |
2481 } while ((n < 0) && (__threadErrno == EINTR)); |
2490 if (n < 0) { |
2482 if (n < 0) { |
2491 errno = __threadErrno; |
2483 errno = __threadErrno; |
2492 } |
2484 } |
2493 |
2485 |
2494 if (allocatedBuffer) { |
2486 if (allocatedBuffer) { |
2495 if (n > 0) { |
2487 if (n > 0) { |
2496 memcpy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, n); |
2488 memcpy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, n); |
2497 } |
2489 } |
2498 free(allocatedBuffer); |
2490 free(allocatedBuffer); |
2499 } |
2491 } |
2500 # else |
2492 # else |
2501 __BEGIN_INTERRUPTABLE__ |
2493 __BEGIN_INTERRUPTABLE__ |
2502 do { |
2494 do { |
2503 alen = sizeof(sa); |
2495 alen = sizeof(sa); |
2504 if (extPtr) { |
2496 if (extPtr) { |
2505 n = recvfrom(sock, extPtr + offs, objSize, _flags, (struct sockaddr *) &sa, &alen); |
2497 n = recvfrom(sock, extPtr + offs, objSize, _flags, (struct sockaddr *) &sa, &alen); |
2506 } else { |
2498 } else { |
2507 n = recvfrom(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, (struct sockaddr *) &sa, &alen); |
2499 n = recvfrom(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, (struct sockaddr *) &sa, &alen); |
2508 } |
2500 } |
2509 } while ((n < 0) && (errno == EINTR)); |
2501 } while ((n < 0) && (errno == EINTR)); |
2510 __END_INTERRUPTABLE__ |
2502 __END_INTERRUPTABLE__ |
2511 # endif |
2503 # endif |
2512 |
2504 |
2513 if (n >= 0) { |
2505 if (n >= 0) { |
2514 if (__isNonNilObject(addr)) { |
2506 if (__isNonNilObject(addr)) { |
2515 char *addrPtr; |
2507 char *addrPtr; |
2516 OBJ oClass; |
2508 OBJ oClass; |
2517 int nInstVars, nInstBytes, objSize; |
2509 int nInstVars, nInstBytes, objSize; |
2518 |
2510 |
2519 oClass = __qClass(addr); |
2511 oClass = __qClass(addr); |
2520 if (! __isBytes(addr) ) |
2512 if (! __isBytes(addr) ) |
2521 goto bad; |
2513 goto bad; |
2522 nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
2514 nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
2523 nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); |
2515 nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); |
2524 objSize = __qSize(addr) - nInstBytes; |
2516 objSize = __qSize(addr) - nInstBytes; |
2525 addrPtr = (char *)__InstPtr(addr) + nInstBytes; |
2517 addrPtr = (char *)__InstPtr(addr) + nInstBytes; |
2526 if (objSize < alen) |
2518 if (objSize < alen) |
2527 goto bad; |
2519 goto bad; |
2528 |
2520 |
2529 /* |
2521 /* |
2530 * extract the datagrams address |
2522 * extract the datagrams address |
2531 */ |
2523 */ |
2532 memcpy(addrPtr, (char *)&sa, alen); |
2524 memcpy(addrPtr, (char *)&sa, alen); |
2533 addrLen = __MKSMALLINT(alen); |
2525 addrLen = __MKSMALLINT(alen); |
2534 } |
2526 } |
2535 } |
2527 } |
2536 if (n < 0) { |
2528 if (n < 0) { |
2537 error = __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2529 error = __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2538 } |
2530 } |
2539 nReceived = __MKSMALLINT(n); |
2531 nReceived = __MKSMALLINT(n); |
2540 } |
2532 } |
2541 #endif |
2533 #endif |
2542 bad: ; |
2534 bad: ; |
2543 %}. |
2535 %}. |
2544 error notNil ifTrue:[ |
2536 error notNil ifTrue:[ |
2545 ^ self readError:error. |
2537 ^ self readError:error. |
2546 ]. |
2538 ]. |
2547 |
2539 |
2548 nReceived notNil ifTrue:[ |
2540 nReceived notNil ifTrue:[ |
2549 addrLen notNil ifTrue:[ |
2541 addrLen notNil ifTrue:[ |
2550 (addr == anAddressBuffer) ifFalse:[ |
2542 (addr == anAddressBuffer) ifFalse:[ |
2551 self obsoleteFeatureWarning:'please use a socketAddress argument'. |
2543 self obsoleteFeatureWarning:'please use a socketAddress argument'. |
2552 |
2544 |
2553 "can be a ByteArray for backward compatibility" |
2545 "can be a ByteArray for backward compatibility" |
2554 anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress). |
2546 anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress). |
2555 ]. |
2547 ]. |
2556 ]. |
2548 ]. |
2557 ^ nReceived |
2549 ^ nReceived |
2558 ]. |
2550 ]. |
2559 " |
2551 " |
2560 arrive here if you try to receive into an invalid buffer |
2552 arrive here if you try to receive into an invalid buffer |
2561 (i.e. not ByteArray-like), |
2553 (i.e. not ByteArray-like), |
2562 or if the addressBuffer is nonNil AND not a SocketAddress/ByteArray |
2554 or if the addressBuffer is nonNil AND not a SocketAddress/ByteArray |
2688 On error, the unix error code is left in the lastErrorNumber |
2680 On error, the unix error code is left in the lastErrorNumber |
2689 instance variable." |
2681 instance variable." |
2690 |
2682 |
2691 |domainClass addr error| |
2683 |domainClass addr error| |
2692 |
2684 |
2693 (anAddressBuffer isKindOf:SocketAddress) ifTrue:[ |
2685 anAddressBuffer isSocketAddress ifTrue:[ |
2694 addr := anAddressBuffer. |
2686 addr := anAddressBuffer. |
2695 ] ifFalse:[ |
2687 ] ifFalse:[ |
2696 anAddressBuffer isByteArray ifFalse:[ |
2688 anAddressBuffer isByteArray ifFalse:[ |
2697 ^ self error:'bad socketAddress argument' |
2689 ^ self error:'bad socketAddress argument' |
2698 ]. |
2690 ]. |
2699 domainClass := self class socketAddressClassForDomain:domain. |
2691 domainClass := self class socketAddressClassForDomain:domain. |
2700 domainClass isNil ifTrue:[ |
2692 domainClass isNil ifTrue:[ |
2701 ^ self error:'invalid (unsupported) domain'. |
2693 ^ self error:'invalid (unsupported) domain'. |
2702 ]. |
2694 ]. |
2703 addr := domainClass hostAddress:anAddressBuffer. |
2695 addr := domainClass hostAddress:anAddressBuffer. |
2704 ]. |
2696 ]. |
2705 %{ |
2697 %{ |
2706 #ifndef NO_SOCKET |
2698 #ifndef NO_SOCKET |
2707 OBJ fp = __INST(handle); |
2699 OBJ fp = __INST(handle); |
2708 |
2700 |
2709 if ((fp != nil) |
2701 if ((fp != nil) |
2710 && __isSmallInteger(startIndex) |
2702 && __isSmallInteger(startIndex) |
2711 && __isSmallInteger(nBytes)) { |
2703 && __isSmallInteger(nBytes)) { |
2712 SOCKET sock; |
2704 SOCKET sock; |
2713 INT objSize; |
2705 INT objSize; |
2714 struct sockaddr *sockaddr_ptr; |
2706 struct sockaddr *sockaddr_ptr; |
2715 union sockaddr_u sa; |
2707 union sockaddr_u sa; |
2716 socklen_t sockaddr_size, alen = 0; |
2708 socklen_t sockaddr_size, alen = 0; |
2717 INT sockAddrOffs; |
2709 INT sockAddrOffs; |
2718 INT n, offs; |
2710 INT n, offs; |
2719 char *extPtr; |
2711 char *extPtr; |
2720 int _flags = __longIntVal(flags); |
2712 int _flags = __longIntVal(flags); |
2721 unsigned long norder; |
2713 unsigned long norder; |
2722 unsigned char *buffer; |
2714 unsigned char *buffer; |
2723 unsigned char *allocatedBuffer = NULL; |
2715 unsigned char *allocatedBuffer = NULL; |
2724 |
2716 |
2725 sock = SOCKET_FROM_FILE_OBJECT(fp); |
2717 sock = SOCKET_FROM_FILE_OBJECT(fp); |
2726 |
2718 |
2727 if (! __isBytes(addr)) { |
2719 if (! __isBytes(addr)) { |
2728 sockaddr_size = 0; |
2720 sockaddr_size = 0; |
2729 sockaddr_ptr = (struct sockaddr *)0; |
2721 sockaddr_ptr = (struct sockaddr *)0; |
2730 } else { |
2722 } else { |
2731 int nIndex; |
2723 int nIndex; |
2732 OBJ cls; |
2724 OBJ cls; |
2733 |
2725 |
2734 sockAddrOffs = 0; |
2726 sockAddrOffs = 0; |
2735 if ((cls = __qClass(addr)) != @global(ByteArray)) |
2727 if ((cls = __qClass(addr)) != @global(ByteArray)) |
2736 sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
2728 sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
2737 nIndex = __qSize(addr) - OHDR_SIZE; |
2729 nIndex = __qSize(addr) - OHDR_SIZE; |
2738 sockaddr_size = nIndex - sockAddrOffs; |
2730 sockaddr_size = nIndex - sockAddrOffs; |
2739 if (sockaddr_size > sizeof(sa)) { |
2731 if (sockaddr_size > sizeof(sa)) { |
2740 console_fprintf(stderr, "Socket [warning]: bad socketAddr\n"); |
2732 console_fprintf(stderr, "Socket [warning]: bad socketAddr\n"); |
2741 goto bad; |
2733 goto bad; |
2742 } |
2734 } |
2743 memcpy(&sa, (__byteArrayVal(addr) + sockAddrOffs), sockaddr_size); |
2735 memcpy(&sa, (__byteArrayVal(addr) + sockAddrOffs), sockaddr_size); |
2744 sockaddr_ptr = (struct sockaddr *)(&sa); |
2736 sockaddr_ptr = (struct sockaddr *)(&sa); |
2745 } |
2737 } |
2746 |
2738 |
2747 if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; |
2739 if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; |
2748 if (__isSmallInteger(nBytes)) { |
2740 if (__isSmallInteger(nBytes)) { |
2749 if (__intVal(nBytes) < objSize) { |
2741 if (__intVal(nBytes) < objSize) { |
2750 objSize = __intVal(nBytes); |
2742 objSize = __intVal(nBytes); |
2751 } |
2743 } |
2752 } |
2744 } |
2753 |
2745 |
2754 #ifdef DO_WRAP_CALLS |
2746 #ifdef DO_WRAP_CALLS |
2755 if (extPtr) { |
2747 if (extPtr) { |
2756 buffer = extPtr + offs; |
2748 buffer = extPtr + offs; |
2757 } else { |
2749 } else { |
2758 allocatedBuffer = buffer = (char *)malloc(objSize); |
2750 allocatedBuffer = buffer = (char *)malloc(objSize); |
2759 bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); |
2751 bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); |
2760 } |
2752 } |
2761 |
2753 |
2762 do { |
2754 do { |
2763 __threadErrno = 0; |
2755 __threadErrno = 0; |
2764 n = (INT)STX_WSA_NOINT_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2756 n = (INT)STX_WSA_NOINT_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2765 } while ((n < 0) && (__threadErrno == EINTR)); |
2757 } while ((n < 0) && (__threadErrno == EINTR)); |
2766 if (n < 0) { |
2758 if (n < 0) { |
2767 errno = __threadErrno; |
2759 errno = __threadErrno; |
2768 } |
2760 } |
2769 |
2761 |
2770 if (allocatedBuffer) { |
2762 if (allocatedBuffer) { |
2771 free(allocatedBuffer); |
2763 free(allocatedBuffer); |
2772 } |
2764 } |
2773 #else |
2765 #else |
2774 __BEGIN_INTERRUPTABLE__ |
2766 __BEGIN_INTERRUPTABLE__ |
2775 do { |
2767 do { |
2776 if (extPtr) { |
2768 if (extPtr) { |
2777 n = sendto(sock, extPtr + offs, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2769 n = sendto(sock, extPtr + offs, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2778 } else { |
2770 } else { |
2779 n = sendto(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2771 n = sendto(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, sockaddr_ptr, sockaddr_size); |
2780 } |
2772 } |
2781 } while ((n < 0) && (errno == EINTR)); |
2773 } while ((n < 0) && (errno == EINTR)); |
2782 __END_INTERRUPTABLE__ |
2774 __END_INTERRUPTABLE__ |
2783 #endif |
2775 #endif |
2784 |
2776 |
2785 if (n < 0) { |
2777 if (n < 0) { |
2786 error = __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2778 error = __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2787 } else { |
2779 } else { |
2788 RETURN (__MKSMALLINT(n)); |
2780 RETURN (__MKSMALLINT(n)); |
2789 } |
2781 } |
2790 } |
2782 } |
2791 #endif |
2783 #endif |
2792 bad: ; |
2784 bad: ; |
2793 %}. |
2785 %}. |
2794 error notNil ifTrue:[ |
2786 error notNil ifTrue:[ |
2795 self writeError:error. |
2787 self writeError:error. |
2796 ]. |
2788 ]. |
2797 |
2789 |
2798 " |
2790 " |
2799 arrive here if you try to send from an invalid buffer |
2791 arrive here if you try to send from an invalid buffer |
2800 (i.e. not ByteArray-like), |
2792 (i.e. not ByteArray-like), |